Network Validation Test Cases

This commit is contained in:
Matthew R Kasun 2021-04-30 23:07:25 -04:00
parent c533bf7183
commit 0e1a5f534f
9 changed files with 726 additions and 491 deletions

View file

@ -7,13 +7,13 @@ import (
"net"
"time"
"github.com/go-playground/validator/v10"
"github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/mongoconn"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
"golang.org/x/crypto/bcrypt"
"gopkg.in/go-playground/validator.v9"
)
func GetPeersList(networkName string) ([]models.PeersResponse, error) {
@ -66,11 +66,11 @@ func ValidateNodeCreate(networkName string, node models.Node) error {
empty := node.Address == ""
return (empty || isIpv4)
})
_ = v.RegisterValidation("address6_check", func(fl validator.FieldLevel) bool {
isIpv6 := functions.IsIpNet(node.Address6)
empty := node.Address6 == ""
return (empty || isIpv6)
})
_ = v.RegisterValidation("address6_check", func(fl validator.FieldLevel) bool {
isIpv6 := functions.IsIpNet(node.Address6)
empty := node.Address6 == ""
return (empty || isIpv6)
})
_ = v.RegisterValidation("endpoint_check", func(fl validator.FieldLevel) bool {
//var isFieldUnique bool = functions.IsFieldUnique(networkName, "endpoint", node.Endpoint)
isIp := functions.IsIpNet(node.Endpoint)
@ -126,66 +126,66 @@ func ValidateNodeCreate(networkName string, node models.Node) error {
func ValidateNodeUpdate(networkName string, node models.Node) error {
v := validator.New()
_ = v.RegisterValidation("address_check", func(fl validator.FieldLevel) bool {
isIpv4 := functions.IsIpNet(node.Address)
empty := node.Address == ""
return (empty || isIpv4)
})
_ = v.RegisterValidation("address6_check", func(fl validator.FieldLevel) bool {
isIpv6 := functions.IsIpNet(node.Address6)
empty := node.Address6 == ""
return (empty || isIpv6)
})
_ = v.RegisterValidation("endpoint_check", func(fl validator.FieldLevel) bool {
//var isFieldUnique bool = functions.IsFieldUnique(networkName, "endpoint", node.Endpoint)
isIp := functions.IsIpNet(node.Address)
v := validator.New()
_ = v.RegisterValidation("address_check", func(fl validator.FieldLevel) bool {
isIpv4 := functions.IsIpNet(node.Address)
empty := node.Address == ""
return (empty || isIpv4)
})
_ = v.RegisterValidation("address6_check", func(fl validator.FieldLevel) bool {
isIpv6 := functions.IsIpNet(node.Address6)
empty := node.Address6 == ""
return (empty || isIpv6)
})
_ = v.RegisterValidation("endpoint_check", func(fl validator.FieldLevel) bool {
//var isFieldUnique bool = functions.IsFieldUnique(networkName, "endpoint", node.Endpoint)
isIp := functions.IsIpNet(node.Address)
empty := node.Endpoint == ""
return (empty || isIp)
})
_ = v.RegisterValidation("localaddress_check", func(fl validator.FieldLevel) bool {
//var isFieldUnique bool = functions.IsFieldUnique(networkName, "endpoint", node.Endpoint)
isIp := functions.IsIpNet(node.LocalAddress)
empty := node.LocalAddress == ""
return (empty || isIp )
})
_ = v.RegisterValidation("macaddress_unique", func(fl validator.FieldLevel) bool {
return true
})
return (empty || isIp)
})
_ = v.RegisterValidation("localaddress_check", func(fl validator.FieldLevel) bool {
//var isFieldUnique bool = functions.IsFieldUnique(networkName, "endpoint", node.Endpoint)
isIp := functions.IsIpNet(node.LocalAddress)
empty := node.LocalAddress == ""
return (empty || isIp)
})
_ = v.RegisterValidation("macaddress_unique", func(fl validator.FieldLevel) bool {
return true
})
_ = v.RegisterValidation("macaddress_valid", func(fl validator.FieldLevel) bool {
_, err := net.ParseMAC(node.MacAddress)
return err == nil
})
_ = v.RegisterValidation("macaddress_valid", func(fl validator.FieldLevel) bool {
_, err := net.ParseMAC(node.MacAddress)
return err == nil
})
_ = v.RegisterValidation("name_valid", func(fl validator.FieldLevel) bool {
isvalid := functions.NameInNodeCharSet(node.Name)
return isvalid
})
_ = v.RegisterValidation("name_valid", func(fl validator.FieldLevel) bool {
isvalid := functions.NameInNodeCharSet(node.Name)
return isvalid
})
_ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool {
_, err := node.GetNetwork()
return err == nil
})
_ = v.RegisterValidation("pubkey_check", func(fl validator.FieldLevel) bool {
empty := node.PublicKey == ""
isBase64 := functions.IsBase64(node.PublicKey)
return (empty || isBase64)
})
_ = v.RegisterValidation("password_check", func(fl validator.FieldLevel) bool {
empty := node.Password == ""
goodLength := len(node.Password) > 5
return (empty || goodLength)
})
_ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool {
_, err := node.GetNetwork()
return err == nil
})
_ = v.RegisterValidation("pubkey_check", func(fl validator.FieldLevel) bool {
empty := node.PublicKey == ""
isBase64 := functions.IsBase64(node.PublicKey)
return (empty || isBase64)
})
_ = v.RegisterValidation("password_check", func(fl validator.FieldLevel) bool {
empty := node.Password == ""
goodLength := len(node.Password) > 5
return (empty || goodLength)
})
err := v.Struct(node)
err := v.Struct(node)
if err != nil {
for _, e := range err.(validator.ValidationErrors) {
fmt.Println(e)
}
}
return err
if err != nil {
for _, e := range err.(validator.ValidationErrors) {
fmt.Println(e)
}
}
return err
}
func UpdateNode(nodechange models.Node, node models.Node) (models.Node, error) {
@ -199,10 +199,10 @@ func UpdateNode(nodechange models.Node, node models.Node) (models.Node, error) {
node.Address = nodechange.Address
notifynetwork = true
}
if nodechange.Address6 != "" {
node.Address6 = nodechange.Address6
notifynetwork = true
}
if nodechange.Address6 != "" {
node.Address6 = nodechange.Address6
notifynetwork = true
}
if nodechange.Name != "" {
node.Name = nodechange.Name
}
@ -379,15 +379,15 @@ func CreateNode(node models.Node, networkName string) (models.Node, error) {
if err != nil {
return node, err
}
fmt.Println("Setting node address: " + node.Address)
fmt.Println("Setting node address: " + node.Address)
node.Address6, err = functions.UniqueAddress6(networkName)
if node.Address6 != "" {
node.Address6, err = functions.UniqueAddress6(networkName)
if node.Address6 != "" {
fmt.Println("Setting node ipv6 address: " + node.Address6)
}
if err != nil {
return node, err
}
return node, err
}
//IDK why these aren't a part of "set defaults. Pretty dumb.
//TODO: This is dumb. Consolidate and fix.

View file

@ -7,14 +7,15 @@ import (
"fmt"
"net/http"
"time"
"github.com/go-playground/validator/v10"
"github.com/gorilla/mux"
"github.com/txn2/txeh"
"github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/mongoconn"
"github.com/txn2/txeh"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
"gopkg.in/go-playground/validator.v9"
)
func dnsHandlers(r *mux.Router) {
@ -32,85 +33,84 @@ func dnsHandlers(r *mux.Router) {
//Gets all nodes associated with network, including pending nodes
func getNodeDNS(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Content-Type", "application/json")
var dns []models.DNSEntry
var params = mux.Vars(r)
var dns []models.DNSEntry
var params = mux.Vars(r)
dns, err := GetNodeDNS(params["network"])
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
//Returns all the nodes in JSON format
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(dns)
//Returns all the nodes in JSON format
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(dns)
}
//Gets all nodes associated with network, including pending nodes
func getAllDNS(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Content-Type", "application/json")
var dns []models.DNSEntry
var dns []models.DNSEntry
networks, err := functions.ListNetworks()
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
for _, net := range networks {
netdns, err := GetDNS(net.NetID)
if err != nil {
for _, net := range networks {
netdns, err := GetDNS(net.NetID)
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
dns = append(dns, netdns...)
}
return
}
dns = append(dns, netdns...)
}
//Returns all the nodes in JSON format
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(dns)
//Returns all the nodes in JSON format
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(dns)
}
func GetNodeDNS(network string) ([]models.DNSEntry, error) {
func GetNodeDNS(network string) ([]models.DNSEntry, error){
var dns []models.DNSEntry
var dns []models.DNSEntry
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
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)
filter := bson.M{"network": network}
filter := bson.M{"network": network}
cur, err := collection.Find(ctx, filter, options.Find().SetProjection(bson.M{"_id": 0}))
cur, err := collection.Find(ctx, filter, options.Find().SetProjection(bson.M{"_id": 0}))
if err != nil {
return dns, err
}
if err != nil {
return dns, err
}
defer cancel()
defer cancel()
for cur.Next(context.TODO()) {
for cur.Next(context.TODO()) {
var entry models.DNSEntry
var entry models.DNSEntry
err := cur.Decode(&entry)
if err != nil {
return dns, err
}
err := cur.Decode(&entry)
if err != nil {
return dns, err
}
// add item our array of nodes
dns = append(dns, entry)
}
// add item our array of nodes
dns = append(dns, entry)
}
//TODO: Another fatal error we should take care of.
if err := cur.Err(); err != nil {
return dns, err
}
//TODO: Another fatal error we should take care of.
if err := cur.Err(); err != nil {
return dns, err
}
return dns, err
}
@ -118,110 +118,110 @@ func GetNodeDNS(network string) ([]models.DNSEntry, error){
//Gets all nodes associated with network, including pending nodes
func getCustomDNS(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Content-Type", "application/json")
var dns []models.DNSEntry
var params = mux.Vars(r)
var dns []models.DNSEntry
var params = mux.Vars(r)
dns, err := GetCustomDNS(params["network"])
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
dns, err := GetCustomDNS(params["network"])
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
//Returns all the nodes in JSON format
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(dns)
//Returns all the nodes in JSON format
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(dns)
}
func GetCustomDNS(network string) ([]models.DNSEntry, error){
func GetCustomDNS(network string) ([]models.DNSEntry, error) {
var dns []models.DNSEntry
var dns []models.DNSEntry
collection := mongoconn.Client.Database("netmaker").Collection("dns")
collection := mongoconn.Client.Database("netmaker").Collection("dns")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"network": network}
filter := bson.M{"network": network}
cur, err := collection.Find(ctx, filter, options.Find().SetProjection(bson.M{"_id": 0}))
cur, err := collection.Find(ctx, filter, options.Find().SetProjection(bson.M{"_id": 0}))
if err != nil {
return dns, err
}
if err != nil {
return dns, err
}
defer cancel()
defer cancel()
for cur.Next(context.TODO()) {
for cur.Next(context.TODO()) {
var entry models.DNSEntry
var entry models.DNSEntry
err := cur.Decode(&entry)
if err != nil {
return dns, err
}
err := cur.Decode(&entry)
if err != nil {
return dns, err
}
// add item our array of nodes
dns = append(dns, entry)
}
// add item our array of nodes
dns = append(dns, entry)
}
//TODO: Another fatal error we should take care of.
if err := cur.Err(); err != nil {
return dns, err
}
//TODO: Another fatal error we should take care of.
if err := cur.Err(); err != nil {
return dns, err
}
return dns, err
return dns, err
}
func GetDNSEntryNum(domain string, network string) (int, error){
func GetDNSEntryNum(domain string, network string) (int, error) {
num := 0
num := 0
entries, err := GetDNS(network)
if err != nil {
return 0, err
}
entries, err := GetDNS(network)
if err != nil {
return 0, err
}
for i := 0; i < len(entries); i++ {
for i := 0; i < len(entries); i++ {
if domain == entries[i].Name {
num++
}
}
if domain == entries[i].Name {
num++
}
}
return num, nil
return num, nil
}
//Gets all nodes associated with network, including pending nodes
func getDNS(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Content-Type", "application/json")
var dns []models.DNSEntry
var params = mux.Vars(r)
var dns []models.DNSEntry
var params = mux.Vars(r)
dns, err := GetDNS(params["network"])
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(dns)
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(dns)
}
func GetDNS(network string) ([]models.DNSEntry, error) {
var dns []models.DNSEntry
dns, err := GetNodeDNS(network)
if err != nil {
return dns, err
}
customdns, err := GetCustomDNS(network)
if err != nil {
return dns, err
}
var dns []models.DNSEntry
dns, err := GetNodeDNS(network)
if err != nil {
return dns, err
}
customdns, err := GetCustomDNS(network)
if err != nil {
return dns, err
}
dns = append(dns, customdns...)
dns = append(dns, customdns...)
return dns, err
}
@ -229,7 +229,7 @@ func createDNS(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var entry models.DNSEntry
var params = mux.Vars(r)
var params = mux.Vars(r)
//get node from body of request
_ = json.NewDecoder(r.Body).Decode(&entry)
@ -243,10 +243,10 @@ func createDNS(w http.ResponseWriter, r *http.Request) {
entry, err = CreateDNS(entry)
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
w.WriteHeader(http.StatusOK)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(entry)
}
@ -258,9 +258,9 @@ func updateDNS(w http.ResponseWriter, r *http.Request) {
var entry models.DNSEntry
//start here
entry, err := GetDNSEntry(params["domain"],params["network"])
entry, err := GetDNSEntry(params["domain"], params["network"])
if err != nil {
returnErrorResponse(w, r, formatError(err, "badrequest"))
returnErrorResponse(w, r, formatError(err, "badrequest"))
return
}
@ -269,21 +269,21 @@ func updateDNS(w http.ResponseWriter, r *http.Request) {
// we decode our body request params
err = json.NewDecoder(r.Body).Decode(&dnschange)
if err != nil {
returnErrorResponse(w, r, formatError(err, "badrequest"))
returnErrorResponse(w, r, formatError(err, "badrequest"))
return
}
err = ValidateDNSUpdate(dnschange, entry)
if err != nil {
returnErrorResponse(w, r, formatError(err, "badrequest"))
returnErrorResponse(w, r, formatError(err, "badrequest"))
return
}
entry, err = UpdateDNS(dnschange, entry)
if err != nil {
returnErrorResponse(w, r, formatError(err, "badrequest"))
returnErrorResponse(w, r, formatError(err, "badrequest"))
return
}
@ -291,92 +291,92 @@ func updateDNS(w http.ResponseWriter, r *http.Request) {
}
func deleteDNS(w http.ResponseWriter, r *http.Request) {
// Set header
w.Header().Set("Content-Type", "application/json")
// Set header
w.Header().Set("Content-Type", "application/json")
// get params
var params = mux.Vars(r)
// get params
var params = mux.Vars(r)
success, err := DeleteDNS(params["domain"], params["network"])
success, err := DeleteDNS(params["domain"], params["network"])
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
} else if !success {
returnErrorResponse(w, r, formatError(errors.New("Delete unsuccessful."), "badrequest"))
return
}
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
} else if !success {
returnErrorResponse(w, r, formatError(errors.New("Delete unsuccessful."), "badrequest"))
return
}
json.NewEncoder(w).Encode(params["domain"] + " deleted.")
json.NewEncoder(w).Encode(params["domain"] + " deleted.")
}
func CreateDNS(entry models.DNSEntry) (models.DNSEntry, error) {
// connect db
collection := mongoconn.Client.Database("netmaker").Collection("dns")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// connect db
collection := mongoconn.Client.Database("netmaker").Collection("dns")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// insert our node to the node db.
_, err := collection.InsertOne(ctx, entry)
// insert our node to the node db.
_, err := collection.InsertOne(ctx, entry)
defer cancel()
defer cancel()
return entry, err
return entry, err
}
func GetDNSEntry(domain string, network string) (models.DNSEntry, error) {
var entry models.DNSEntry
var entry models.DNSEntry
collection := mongoconn.Client.Database("netmaker").Collection("dns")
collection := mongoconn.Client.Database("netmaker").Collection("dns")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"name": domain, "network": network}
err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&entry)
filter := bson.M{"name": domain, "network": network}
err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&entry)
defer cancel()
defer cancel()
return entry, err
return entry, err
}
func UpdateDNS(dnschange models.DNSEntry, entry models.DNSEntry) (models.DNSEntry, error) {
queryDNS := entry.Name
queryDNS := entry.Name
if dnschange.Name != "" {
entry.Name = dnschange.Name
}
if dnschange.Address != "" {
entry.Address = dnschange.Address
}
//collection := mongoconn.ConnectDB()
collection := mongoconn.Client.Database("netmaker").Collection("dns")
if dnschange.Name != "" {
entry.Name = dnschange.Name
}
if dnschange.Address != "" {
entry.Address = dnschange.Address
}
//collection := mongoconn.ConnectDB()
collection := mongoconn.Client.Database("netmaker").Collection("dns")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// Create filter
filter := bson.M{"name": queryDNS}
// Create filter
filter := bson.M{"name": queryDNS}
// prepare update model.
update := bson.D{
{"$set", bson.D{
{"name", entry.Name},
{"address", entry.Address},
}},
}
var dnsupdate models.DNSEntry
// prepare update model.
update := bson.D{
{"$set", bson.D{
{"name", entry.Name},
{"address", entry.Address},
}},
}
var dnsupdate models.DNSEntry
errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&dnsupdate)
if errN != nil {
fmt.Println("Could not update: ")
fmt.Println(errN)
} else {
fmt.Println("DNS Entry updated successfully.")
}
errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&dnsupdate)
if errN != nil {
fmt.Println("Could not update: ")
fmt.Println(errN)
} else {
fmt.Println("DNS Entry updated successfully.")
}
defer cancel()
defer cancel()
return dnsupdate, errN
return dnsupdate, errN
}
func DeleteDNS(domain string, network string) (bool, error) {
@ -385,7 +385,7 @@ func DeleteDNS(domain string, network string) (bool, error) {
collection := mongoconn.Client.Database("netmaker").Collection("dns")
filter := bson.M{"name": domain, "network": network}
filter := bson.M{"name": domain, "network": network}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
@ -403,31 +403,30 @@ func DeleteDNS(domain string, network string) (bool, error) {
}
func pushDNS(w http.ResponseWriter, r *http.Request) {
// Set header
w.Header().Set("Content-Type", "application/json")
// Set header
w.Header().Set("Content-Type", "application/json")
err := WriteHosts()
err := WriteHosts()
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
json.NewEncoder(w).Encode("DNS Pushed to CoreDNS")
json.NewEncoder(w).Encode("DNS Pushed to CoreDNS")
}
func WriteHosts() error {
//hostfile, err := txeh.NewHostsDefault()
hostfile := txeh.Hosts{}
/*
if err != nil {
return err
}
if err != nil {
return err
}
*/
networks, err := functions.ListNetworks()
if err != nil {
return err
}
if err != nil {
return err
}
for _, net := range networks {
dns, err := GetDNS(net.NetID)
@ -438,7 +437,7 @@ func WriteHosts() error {
hostfile.AddHost(entry.Address, entry.Name+"."+entry.Network)
if err != nil {
return err
}
}
}
}
err = hostfile.SaveAs("./config/netmaker.hosts")
@ -448,9 +447,9 @@ func WriteHosts() error {
func ValidateDNSCreate(entry models.DNSEntry) error {
v := validator.New()
fmt.Println("Validating DNS: " + entry.Name)
fmt.Println(" Address: " + entry.Address)
fmt.Println(" Network: " + entry.Network)
fmt.Println("Validating DNS: " + entry.Name)
fmt.Println(" Address: " + entry.Address)
fmt.Println(" Network: " + entry.Network)
_ = v.RegisterValidation("name_unique", func(fl validator.FieldLevel) bool {
num, err := GetDNSEntryNum(entry.Name, entry.Network)
@ -459,19 +458,19 @@ func ValidateDNSCreate(entry models.DNSEntry) error {
_ = v.RegisterValidation("name_valid", func(fl validator.FieldLevel) bool {
isvalid := functions.NameInDNSCharSet(entry.Name)
notEmptyCheck := len(entry.Name) > 0
notEmptyCheck := len(entry.Name) > 0
return isvalid && notEmptyCheck
})
_ = v.RegisterValidation("address_valid", func(fl validator.FieldLevel) bool {
notEmptyCheck := len(entry.Address) > 0
isIp := functions.IsIpNet(entry.Address)
isIp := functions.IsIpNet(entry.Address)
return notEmptyCheck && isIp
})
_ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool {
_, err := functions.GetParentNetwork(entry.Network)
return err == nil
})
_ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool {
_, err := functions.GetParentNetwork(entry.Network)
return err == nil
})
err := v.Struct(entry)
@ -485,41 +484,39 @@ func ValidateDNSCreate(entry models.DNSEntry) error {
func ValidateDNSUpdate(change models.DNSEntry, entry models.DNSEntry) error {
v := validator.New()
v := validator.New()
_ = v.RegisterValidation("name_unique", func(fl validator.FieldLevel) bool {
_ = v.RegisterValidation("name_unique", func(fl validator.FieldLevel) bool {
goodNum := false
num, err := GetDNSEntryNum(entry.Name, entry.Network)
num, err := GetDNSEntryNum(entry.Name, entry.Network)
if change.Name != entry.Name {
goodNum = num == 0
} else {
goodNum = num == 1
goodNum = num == 1
}
return err == nil && goodNum
})
})
_ = v.RegisterValidation("name_valid", func(fl validator.FieldLevel) bool {
isvalid := functions.NameInDNSCharSet(entry.Name)
notEmptyCheck := entry.Name != ""
return isvalid && notEmptyCheck
})
_ = v.RegisterValidation("name_valid", func(fl validator.FieldLevel) bool {
isvalid := functions.NameInDNSCharSet(entry.Name)
notEmptyCheck := entry.Name != ""
return isvalid && notEmptyCheck
})
_ = v.RegisterValidation("address_valid", func(fl validator.FieldLevel) bool {
_ = v.RegisterValidation("address_valid", func(fl validator.FieldLevel) bool {
isValid := true
if entry.Address != "" {
isValid = functions.IsIpNet(entry.Address)
}
return isValid
})
})
err := v.Struct(entry)
err := v.Struct(entry)
if err != nil {
for _, e := range err.(validator.ValidationErrors) {
fmt.Println(e)
}
}
return err
if err != nil {
for _, e := range err.(validator.ValidationErrors) {
fmt.Println(e)
}
}
return err
}

View file

@ -7,17 +7,19 @@ import (
"errors"
"fmt"
"net/http"
"os"
"strings"
"time"
"os"
"github.com/go-playground/validator/v10"
"github.com/gorilla/mux"
"github.com/gravitl/netmaker/config"
"github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/mongoconn"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"gopkg.in/go-playground/validator.v9"
)
func networkHandlers(r *mux.Router) {
@ -83,7 +85,7 @@ func securityCheck(next http.Handler) http.HandlerFunc {
//Consider a more secure way of setting master key
func authenticateMaster(tokenString string) bool {
if tokenString == config.Config.Server.MasterKey || (tokenString == os.Getenv("MASTER_KEY") && tokenString != "") {
if tokenString == config.Config.Server.MasterKey || (tokenString == os.Getenv("MASTER_KEY") && tokenString != "") {
return true
}
return false
@ -104,7 +106,7 @@ func getNetworks(w http.ResponseWriter, r *http.Request) {
}
}
func validateNetworkUpdate(network models.Network) error {
func ValidateNetworkUpdate(network models.Network) error {
v := validator.New()
@ -112,10 +114,10 @@ func validateNetworkUpdate(network models.Network) error {
isvalid := fl.Field().String() == "" || functions.IsIpCIDR(fl.Field().String())
return isvalid
})
_ = v.RegisterValidation("addressrange6_valid", func(fl validator.FieldLevel) bool {
isvalid := fl.Field().String() == "" || functions.IsIpCIDR(fl.Field().String())
return isvalid
})
_ = v.RegisterValidation("addressrange6_valid", func(fl validator.FieldLevel) bool {
isvalid := fl.Field().String() == "" || functions.IsIpCIDR(fl.Field().String())
return isvalid
})
_ = v.RegisterValidation("localrange_valid", func(fl validator.FieldLevel) bool {
isvalid := fl.Field().String() == "" || functions.IsIpCIDR(fl.Field().String())
@ -140,34 +142,33 @@ func validateNetworkUpdate(network models.Network) error {
return err
}
func validateNetworkCreate(network models.Network) error {
func ValidateNetworkCreate(network models.Network) error {
v := validator.New()
_ = v.RegisterValidation("addressrange_valid", func(fl validator.FieldLevel) bool {
isvalid := functions.IsIpCIDR(fl.Field().String())
return isvalid
})
_ = v.RegisterValidation("addressrange6_valid", func(fl validator.FieldLevel) bool {
// _ = v.RegisterValidation("addressrange_valid", func(fl validator.FieldLevel) bool {
// isvalid := functions.IsIpCIDR(fl.Field().String())
// return isvalid
// })
_ = v.RegisterValidation("addressrange6_valid", func(fl validator.FieldLevel) bool {
isvalid := true
if *network.IsDualStack {
isvalid = functions.IsIpCIDR(fl.Field().String())
}
return isvalid
})
_ = v.RegisterValidation("localrange_valid", func(fl validator.FieldLevel) bool {
isvalid := fl.Field().String() == "" || functions.IsIpCIDR(fl.Field().String())
return isvalid
})
//
// _ = v.RegisterValidation("localrange_valid", func(fl validator.FieldLevel) bool {
// isvalid := fl.Field().String() == "" || functions.IsIpCIDR(fl.Field().String())
// return isvalid
// })
//
_ = v.RegisterValidation("netid_valid", func(fl validator.FieldLevel) bool {
isFieldUnique, _ := functions.IsNetworkNameUnique(fl.Field().String())
inCharSet := functions.NameInNetworkCharSet(fl.Field().String())
return isFieldUnique && inCharSet
// inCharSet := functions.NameInNetworkCharSet(fl.Field().String())
return isFieldUnique
})
//
_ = v.RegisterValidation("displayname_unique", func(fl validator.FieldLevel) bool {
isFieldUnique, _ := functions.IsNetworkDisplayNameUnique(fl.Field().String())
return isFieldUnique
@ -230,16 +231,16 @@ func keyUpdate(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"netid": params["networkname"]}
// prepare update model.
update := bson.D{
{"$set", bson.D{
{"addressrange", network.AddressRange},
{"addressrange6", network.AddressRange6},
{"displayname", network.DisplayName},
{"defaultlistenport", network.DefaultListenPort},
{"defaultpostup", network.DefaultPostUp},
{"defaultpostdown", network.DefaultPostDown},
filter := bson.M{"netid": params["networkname"]}
// prepare update model.
update := bson.D{
{"$set", bson.D{
{"addressrange", network.AddressRange},
{"addressrange6", network.AddressRange6},
{"displayname", network.DisplayName},
{"defaultlistenport", network.DefaultListenPort},
{"defaultpostup", network.DefaultPostUp},
{"defaultpostdown", network.DefaultPostDown},
{"defaultkeepalive", network.DefaultKeepalive},
{"keyupdatetimestamp", network.KeyUpdateTimeStamp},
{"defaultsaveconfig", network.DefaultSaveConfig},
@ -248,8 +249,8 @@ func keyUpdate(w http.ResponseWriter, r *http.Request) {
{"networklastmodified", network.NetworkLastModified},
{"allowmanualsignup", network.AllowManualSignUp},
{"checkininterval", network.DefaultCheckInInterval},
}},
}
}},
}
err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
@ -317,14 +318,14 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) {
if networkChange.AddressRange == "" {
networkChange.AddressRange = network.AddressRange
}
if networkChange.AddressRange6 == "" {
networkChange.AddressRange6 = network.AddressRange6
}
if networkChange.AddressRange6 == "" {
networkChange.AddressRange6 = network.AddressRange6
}
if networkChange.NetID == "" {
networkChange.NetID = network.NetID
}
err = validateNetworkUpdate(networkChange)
err = ValidateNetworkUpdate(networkChange)
if err != nil {
returnErrorResponse(w, r, formatError(err, "badrequest"))
return
@ -366,9 +367,9 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) {
if networkChange.IsLocal != nil {
network.IsLocal = networkChange.IsLocal
}
if networkChange.IsDualStack != nil {
network.IsDualStack = networkChange.IsDualStack
}
if networkChange.IsDualStack != nil {
network.IsDualStack = networkChange.IsDualStack
}
if networkChange.DefaultListenPort != 0 {
network.DefaultListenPort = networkChange.DefaultListenPort
haschange = true
@ -409,26 +410,26 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) {
if haschange {
network.SetNetworkLastModified()
}
// prepare update model.
update := bson.D{
{"$set", bson.D{
{"addressrange", network.AddressRange},
{"addressrange6", network.AddressRange6},
{"displayname", network.DisplayName},
{"defaultlistenport", network.DefaultListenPort},
{"defaultpostup", network.DefaultPostUp},
{"defaultpostdown", network.DefaultPostDown},
{"defaultkeepalive", network.DefaultKeepalive},
{"defaultsaveconfig", network.DefaultSaveConfig},
{"defaultinterface", network.DefaultInterface},
{"nodeslastmodified", network.NodesLastModified},
{"networklastmodified", network.NetworkLastModified},
{"allowmanualsignup", network.AllowManualSignUp},
{"localrange", network.LocalRange},
{"islocal", network.IsLocal},
{"isdualstack", network.IsDualStack},
{"checkininterval", network.DefaultCheckInInterval},
}},
// prepare update model.
update := bson.D{
{"$set", bson.D{
{"addressrange", network.AddressRange},
{"addressrange6", network.AddressRange6},
{"displayname", network.DisplayName},
{"defaultlistenport", network.DefaultListenPort},
{"defaultpostup", network.DefaultPostUp},
{"defaultpostdown", network.DefaultPostDown},
{"defaultkeepalive", network.DefaultKeepalive},
{"defaultsaveconfig", network.DefaultSaveConfig},
{"defaultinterface", network.DefaultInterface},
{"nodeslastmodified", network.NodesLastModified},
{"networklastmodified", network.NetworkLastModified},
{"allowmanualsignup", network.AllowManualSignUp},
{"localrange", network.LocalRange},
{"islocal", network.IsLocal},
{"isdualstack", network.IsDualStack},
{"checkininterval", network.DefaultCheckInInterval},
}},
}
err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
@ -472,36 +473,42 @@ func deleteNetwork(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var params = mux.Vars(r)
network := params["networkname"]
count, err := DeleteNetwork(network)
nodecount, err := functions.GetNetworkNodeNumber(params["networkname"])
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
returnErrorResponse(w, r, formatError(err, "badrequest"))
return
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(count)
}
func DeleteNetwork(network string) (*mongo.DeleteResult, error) {
none := &mongo.DeleteResult{}
nodecount, err := functions.GetNetworkNodeNumber(network)
if err != nil {
//returnErrorResponse(w, r, formatError(err, "internal"))
return none, err
} else if nodecount > 0 {
errorResponse := models.ErrorResponse{
Code: http.StatusForbidden, Message: "W1R3: Node check failed. All nodes must be deleted before deleting network.",
}
returnErrorResponse(w, r, errorResponse)
return
//errorResponse := models.ErrorResponse{
// Code: http.StatusForbidden, Message: "W1R3: Node check failed. All nodes must be deleted before deleting network.",
//}
//returnErrorResponse(w, r, errorResponse)
return none, errors.New("Node check failed. All nodes must be deleted before deleting network")
}
collection := mongoconn.Client.Database("netmaker").Collection("networks")
filter := bson.M{"netid": params["networkname"]}
filter := bson.M{"netid": network}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
deleteResult, err := collection.DeleteOne(ctx, filter)
defer cancel()
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
//returnErrorResponse(w, r, formatError(err, "internal"))
return none, err
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(deleteResult)
return deleteResult, nil
}
//Create a network
@ -519,6 +526,16 @@ func createNetwork(w http.ResponseWriter, r *http.Request) {
return
}
err = CreateNetwork(network)
if err != nil {
returnErrorResponse(w, r, formatError(err, "badrequest"))
return
}
w.WriteHeader(http.StatusOK)
//json.NewEncoder(w).Encode(result)
}
func CreateNetwork(network models.Network) error {
//TODO: Not really doing good validation here. Same as createNode, updateNode, and updateNetwork
//Need to implement some better validation across the board
@ -526,15 +543,15 @@ func createNetwork(w http.ResponseWriter, r *http.Request) {
falsevar := false
network.IsLocal = &falsevar
}
if network.IsDualStack == nil {
falsevar := false
network.IsDualStack = &falsevar
}
if network.IsDualStack == nil {
falsevar := false
network.IsDualStack = &falsevar
}
err = validateNetworkCreate(network)
err := ValidateNetworkCreate(network)
if err != nil {
returnErrorResponse(w, r, formatError(err, "badrequest"))
return
//returnErrorResponse(w, r, formatError(err, "badrequest"))
return err
}
network.SetDefaults()
network.SetNodesLastModified()
@ -546,15 +563,12 @@ func createNetwork(w http.ResponseWriter, r *http.Request) {
// insert our network into the network table
result, err := collection.InsertOne(ctx, network)
fmt.Printf("=========%T, %v\n", result, result)
defer cancel()
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
return err
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(result)
return nil
}
// BEGIN KEY MANAGEMENT SECTION

View file

@ -0,0 +1,221 @@
package controller
import (
"testing"
"github.com/gravitl/netmaker/models"
"github.com/stretchr/testify/assert"
)
type NetworkValidationTestCase struct {
testname string
network models.Network
errMessage string
}
func TestGetNetworks(t *testing.T) {
//calls functions.ListNetworks --- nothing to be don
}
func TestCreateNetwork(t *testing.T) {
}
func TestGetNetwork(t *testing.T) {
}
func TestUpdateNetwork(t *testing.T) {
}
func TestDeleteNetwork(t *testing.T) {
}
func TestKeyUpdate(t *testing.T) {
}
func TestCreateKey(t *testing.T) {
}
func TestGetKey(t *testing.T) {
}
func TestDeleteKey(t *testing.T) {
}
func TestSecurityCheck(t *testing.T) {
}
func TestValidateNetworkUpdate(t *testing.T) {
}
func TestValidateNetworkCreate(t *testing.T) {
yes := true
no := false
//DeleteNetworks
cases := []NetworkValidationTestCase{
NetworkValidationTestCase{
testname: "InvalidAddress",
network: models.Network{
AddressRange: "10.0.0.256",
NetID: "skynet",
IsDualStack: &no,
},
errMessage: "Field validation for 'AddressRange' failed on the 'cidr' tag",
},
NetworkValidationTestCase{
testname: "BadDisplayName",
network: models.Network{
AddressRange: "10.0.0.1/24",
NetID: "skynet",
DisplayName: "skynet*",
IsDualStack: &no,
},
errMessage: "Field validation for 'DisplayName' failed on the 'alphanum' tag",
},
NetworkValidationTestCase{
testname: "DisplayNameTooLong",
network: models.Network{
AddressRange: "10.0.0.1/24",
NetID: "skynet",
DisplayName: "Thisisareallylongdisplaynamethatistoolong",
IsDualStack: &no,
},
errMessage: "Field validation for 'DisplayName' failed on the 'max' tag",
},
NetworkValidationTestCase{
testname: "DisplayNameTooShort",
network: models.Network{
AddressRange: "10.0.0.1/24",
NetID: "skynet",
DisplayName: "1",
IsDualStack: &no,
},
errMessage: "Field validation for 'DisplayName' failed on the 'min' tag",
},
NetworkValidationTestCase{
testname: "NetIDMissing",
network: models.Network{
AddressRange: "10.0.0.1/24",
IsDualStack: &no,
},
errMessage: "Field validation for 'NetID' failed on the 'required' tag",
},
NetworkValidationTestCase{
testname: "InvalidNetID",
network: models.Network{
AddressRange: "10.0.0.1/24",
NetID: "contains spaces",
IsDualStack: &no,
},
errMessage: "Field validation for 'NetID' failed on the 'alphanum' tag",
},
NetworkValidationTestCase{
testname: "NetIDTooShort",
network: models.Network{
AddressRange: "10.0.0.1/24",
NetID: "",
IsDualStack: &no,
},
errMessage: "Field validation for 'NetID' failed on the 'required' tag",
},
NetworkValidationTestCase{
testname: "NetIDTooLong",
network: models.Network{
AddressRange: "10.0.0.1/24",
NetID: "LongNetIDName",
IsDualStack: &no,
},
errMessage: "Field validation for 'NetID' failed on the 'max' tag",
},
NetworkValidationTestCase{
testname: "ListenPortTooLow",
network: models.Network{
AddressRange: "10.0.0.1/24",
NetID: "skynet",
DefaultListenPort: 1023,
IsDualStack: &no,
},
errMessage: "Field validation for 'DefaultListenPort' failed on the 'min' tag",
},
NetworkValidationTestCase{
testname: "ListenPortTooHigh",
network: models.Network{
AddressRange: "10.0.0.1/24",
NetID: "skynet",
DefaultListenPort: 65536,
IsDualStack: &no,
},
errMessage: "Field validation for 'DefaultListenPort' failed on the 'max' tag",
},
NetworkValidationTestCase{
testname: "KeepAliveTooBig",
network: models.Network{
AddressRange: "10.0.0.1/24",
NetID: "skynet",
DefaultKeepalive: 1010,
IsDualStack: &no,
},
errMessage: "Field validation for 'DefaultKeepalive' failed on the 'max' tag",
},
NetworkValidationTestCase{
testname: "InvalidLocalRange",
network: models.Network{
AddressRange: "10.0.0.1/24",
NetID: "skynet",
LocalRange: "192.168.0.1",
IsDualStack: &no,
},
errMessage: "Field validation for 'LocalRange' failed on the 'cidr' tag",
},
NetworkValidationTestCase{
testname: "DualStackWithoutIPv6",
network: models.Network{
AddressRange: "10.0.0.1/24",
NetID: "skynet",
IsDualStack: &yes,
},
errMessage: "Field validation for 'AddressRange6' failed on the 'addressrange6_valid' tag",
},
NetworkValidationTestCase{
testname: "CheckInIntervalTooBig",
network: models.Network{
AddressRange: "10.0.0.1/24",
NetID: "skynet",
IsDualStack: &no,
DefaultCheckInInterval: 100001,
},
errMessage: "Field validation for 'DefaultCheckInInterval' failed on the 'max' tag",
},
NetworkValidationTestCase{
testname: "CheckInIntervalTooSmall",
network: models.Network{
AddressRange: "10.0.0.1/24",
NetID: "skynet",
IsDualStack: &no,
DefaultCheckInInterval: 1,
},
errMessage: "Field validation for 'DefaultCheckInInterval' failed on the 'min' tag",
},
}
for _, tc := range cases {
t.Run(tc.testname, func(t *testing.T) {
err := ValidateNetworkCreate(tc.network)
assert.NotNil(t, err)
assert.Contains(t, err.Error(), tc.errMessage)
})
}
t.Run("DuplicateNetID", func(t *testing.T) {
var net1, net2 models.Network
net1.NetID = "skylink"
net1.AddressRange = "10.0.0.1/24"
net1.DisplayName = "mynetwork"
net2.NetID = "skylink"
net2.AddressRange = "10.0.1.1/24"
net2.IsDualStack = &no
err := CreateNetwork(net1)
assert.Nil(t, err)
err = ValidateNetworkCreate(net2)
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "Field validation for 'NetID' failed on the 'netid_valid' tag")
})
t.Run("DuplicateDisplayName", func(t *testing.T) {
var network models.Network
network.NetID = "wirecat"
network.AddressRange = "10.0.100.1/24"
network.IsDualStack = &no
network.DisplayName = "mynetwork"
err := ValidateNetworkCreate(network)
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "Field validation for 'DisplayName' failed on the 'displayname_unique' tag")
})
}

View file

@ -9,6 +9,7 @@ import (
"strings"
"time"
"github.com/go-playground/validator/v10"
"github.com/gorilla/mux"
"github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/models"
@ -17,7 +18,6 @@ import (
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"golang.org/x/crypto/bcrypt"
"gopkg.in/go-playground/validator.v9"
)
func userHandlers(r *mux.Router) {

View file

@ -33,17 +33,17 @@ func TestHasAdmin(t *testing.T) {
assert.Nil(t, err)
user := models.User{"admin", "password", true}
_, err = CreateUser(user)
assert.Nil(t, err, err)
assert.Nil(t, err)
t.Run("AdminExists", func(t *testing.T) {
found, err := HasAdmin()
assert.Nil(t, err, err)
assert.Nil(t, err)
assert.True(t, found)
})
t.Run("NoUser", func(t *testing.T) {
_, err := DeleteUser("admin")
assert.Nil(t, err, err)
assert.Nil(t, err)
found, err := HasAdmin()
assert.Nil(t, err, err)
assert.Nil(t, err)
assert.False(t, found)
})
}
@ -52,35 +52,35 @@ func TestCreateUser(t *testing.T) {
user := models.User{"admin", "password", true}
t.Run("NoUser", func(t *testing.T) {
_, err := DeleteUser("admin")
assert.Nil(t, err, err)
assert.Nil(t, err)
admin, err := CreateUser(user)
assert.Nil(t, err, err)
assert.Nil(t, err)
assert.Equal(t, user.UserName, admin.UserName)
})
t.Run("AdminExists", func(t *testing.T) {
_, err := CreateUser(user)
assert.NotNil(t, err, err)
assert.NotNil(t, err)
assert.Equal(t, "Admin already Exists", err.Error())
})
}
func TestDeleteUser(t *testing.T) {
hasadmin, err := HasAdmin()
assert.Nil(t, err, err)
assert.Nil(t, err)
if !hasadmin {
user := models.User{"admin", "pasword", true}
_, err := CreateUser(user)
assert.Nil(t, err, err)
assert.Nil(t, err)
}
t.Run("ExistingUser", func(t *testing.T) {
deleted, err := DeleteUser("admin")
assert.Nil(t, err, err)
assert.Nil(t, err)
assert.True(t, deleted)
t.Log(deleted, err)
})
t.Run("NonExistantUser", func(t *testing.T) {
deleted, err := DeleteUser("admin")
assert.Nil(t, err, err)
assert.Nil(t, err)
assert.False(t, deleted)
})
}
@ -91,33 +91,37 @@ func TestValidateUser(t *testing.T) {
user.UserName = "admin"
user.Password = "validpass"
err := ValidateUser("create", user)
assert.Nil(t, err, err)
assert.Nil(t, err)
})
t.Run("ValidUpdate", func(t *testing.T) {
user.UserName = "admin"
user.Password = "password"
err := ValidateUser("update", user)
assert.Nil(t, err, err)
assert.Nil(t, err)
})
t.Run("InvalidUserName", func(t *testing.T) {
user.UserName = "invalid*"
err := ValidateUser("update", user)
assert.NotNil(t, err, err)
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "Field validation for 'UserName' failed")
})
t.Run("ShortUserName", func(t *testing.T) {
user.UserName = "12"
err := ValidateUser("create", user)
assert.NotNil(t, err, err)
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "Field validation for 'UserName' failed")
})
t.Run("EmptyPassword", func(t *testing.T) {
user.Password = ""
err := ValidateUser("create", user)
assert.NotNil(t, err, err)
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "Field validation for 'Password' failed")
})
t.Run("ShortPassword", func(t *testing.T) {
user.Password = "123"
err := ValidateUser("create", user)
assert.NotNil(t, err, err)
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "Field validation for 'Password' failed")
})
}
@ -125,18 +129,18 @@ func TestGetUser(t *testing.T) {
t.Run("UserExisits", func(t *testing.T) {
user := models.User{"admin", "password", true}
hasadmin, err := HasAdmin()
assert.Nil(t, err, err)
assert.Nil(t, err)
if !hasadmin {
_, err := CreateUser(user)
assert.Nil(t, err, err)
assert.Nil(t, err)
}
admin, err := GetUser("admin")
assert.Nil(t, err, err)
assert.Nil(t, err)
assert.Equal(t, user.UserName, admin.UserName)
})
t.Run("NonExistantUser", func(t *testing.T) {
_, err := DeleteUser("admin")
assert.Nil(t, err, err)
assert.Nil(t, err)
admin, err := GetUser("admin")
assert.Equal(t, "mongo: no documents in result", err.Error())
assert.Equal(t, "", admin.UserName)
@ -149,14 +153,14 @@ func TestUpdateUser(t *testing.T) {
t.Run("UserExisits", func(t *testing.T) {
_, err := DeleteUser("admin")
_, err = CreateUser(user)
assert.Nil(t, err, err)
assert.Nil(t, err)
admin, err := UpdateUser(newuser, user)
assert.Nil(t, err, err)
assert.Nil(t, err)
assert.Equal(t, newuser.UserName, admin.UserName)
})
t.Run("NonExistantUser", func(t *testing.T) {
_, err := DeleteUser("hello")
assert.Nil(t, err, err)
assert.Nil(t, err)
_, err = UpdateUser(newuser, user)
assert.Equal(t, "mongo: no documents in result", err.Error())
})
@ -165,12 +169,12 @@ func TestUpdateUser(t *testing.T) {
func TestValidateToken(t *testing.T) {
t.Run("EmptyToken", func(t *testing.T) {
err := ValidateToken("")
assert.NotNil(t, err, err)
assert.NotNil(t, err)
assert.Equal(t, "Missing Auth Token.", err.Error())
})
t.Run("InvalidToken", func(t *testing.T) {
err := ValidateToken("Bearer: badtoken")
assert.NotNil(t, err, err)
assert.NotNil(t, err)
assert.Equal(t, "Error Verifying Auth Token", err.Error())
})
t.Run("InvalidUser", func(t *testing.T) {
@ -179,7 +183,7 @@ func TestValidateToken(t *testing.T) {
})
t.Run("ValidToken", func(t *testing.T) {
err := ValidateToken("Bearer: secretkey")
assert.Nil(t, err, err)
assert.Nil(t, err)
})
}
@ -189,7 +193,7 @@ func TestVerifyAuthRequest(t *testing.T) {
authRequest.UserName = ""
authRequest.Password = "Password"
jwt, err := VerifyAuthRequest(authRequest)
assert.NotNil(t, err, err)
assert.NotNil(t, err)
assert.Equal(t, "", jwt)
assert.Equal(t, "Username can't be empty", err.Error())
})
@ -197,7 +201,7 @@ func TestVerifyAuthRequest(t *testing.T) {
authRequest.UserName = "admin"
authRequest.Password = ""
jwt, err := VerifyAuthRequest(authRequest)
assert.NotNil(t, err, err)
assert.NotNil(t, err)
assert.Equal(t, "", jwt)
assert.Equal(t, "Password can't be empty", err.Error())
})
@ -206,7 +210,7 @@ func TestVerifyAuthRequest(t *testing.T) {
authRequest.UserName = "admin"
authRequest.Password = "password"
jwt, err := VerifyAuthRequest(authRequest)
assert.NotNil(t, err, err)
assert.NotNil(t, err)
assert.Equal(t, "", jwt)
assert.Equal(t, "User admin not found", err.Error())
})
@ -218,7 +222,7 @@ func TestVerifyAuthRequest(t *testing.T) {
assert.Nil(t, err)
authRequest := models.UserAuthParams{"admin", "admin"}
jwt, err := VerifyAuthRequest(authRequest)
assert.NotNil(t, err, err)
assert.NotNil(t, err)
assert.Equal(t, "", jwt)
assert.Equal(t, "User is not an admin", err.Error())
})
@ -229,14 +233,14 @@ func TestVerifyAuthRequest(t *testing.T) {
assert.Nil(t, err)
authRequest := models.UserAuthParams{"admin", "badpass"}
jwt, err := VerifyAuthRequest(authRequest)
assert.NotNil(t, err, err)
assert.NotNil(t, err)
assert.Equal(t, "", jwt)
assert.Equal(t, "Wrong Password", err.Error())
})
t.Run("Success", func(t *testing.T) {
authRequest := models.UserAuthParams{"admin", "password"}
jwt, err := VerifyAuthRequest(authRequest)
assert.Nil(t, err, err)
assert.Nil(t, err)
assert.NotNil(t, jwt)
})
}

8
go.mod
View file

@ -3,15 +3,13 @@ module github.com/gravitl/netmaker
go 1.15
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/go-playground/universal-translator v0.17.0 // indirect
github.com/go-playground/validator/v10 v10.5.0
github.com/golang/protobuf v1.4.3
github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0
github.com/leodido/go-urn v1.2.0 // indirect
github.com/stretchr/testify v1.6.1
github.com/txn2/txeh v1.3.0 // indirect
github.com/txn2/txeh v1.3.0
go.mongodb.org/mongo-driver v1.4.3
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
@ -22,7 +20,5 @@ require (
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200609130330-bd2cb7843e1b
google.golang.org/genproto v0.0.0-20210201151548-94839c025ad4 // indirect
google.golang.org/grpc v1.35.0
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
gopkg.in/go-playground/validator.v9 v9.31.0
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
)

8
go.sum
View file

@ -22,10 +22,14 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.5.0 h1:X9rflw/KmpACwT8zdrm1upefpvdy6ur8d1kWyq6sg3E=
github.com/go-playground/validator/v10 v10.5.0/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
@ -261,10 +265,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M=
gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View file

@ -1,74 +1,77 @@
package models
import (
// "../mongoconn"
"go.mongodb.org/mongo-driver/bson/primitive"
"time"
// "../mongoconn"
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
//Network Struct
//At some point, need to replace all instances of Name with something else like Identifier
type Network struct {
ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"`
AddressRange string `json:"addressrange" bson:"addressrange" validate:"required,addressrange_valid"`
AddressRange6 string `json:"addressrange6" bson:"addressrange6" validate:"addressrange6_valid"`
DisplayName string `json:"displayname,omitempty" bson:"displayname,omitempty" validate:"omitempty,displayname_unique,min=1,max=100"`
NetID string `json:"netid" bson:"netid" validate:"required,netid_valid,min=1,max=12"`
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,numeric,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,numeric,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:"localrange_valid"`
DefaultCheckInInterval int32 `json:"checkininterval,omitempty" bson:"checkininterval,omitempty" validate:"omitempty,numeric,min=1,max=100000"`
ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"`
AddressRange string `json:"addressrange" bson:"addressrange" validate:"required,cidr"`
// 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:"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"`
}
//TODO:
//Not sure if we need the below two functions. Got rid of one of the calls. May want to revisit
func(network *Network) SetNodesLastModified(){
network.NodesLastModified = time.Now().Unix()
func (network *Network) SetNodesLastModified() {
network.NodesLastModified = time.Now().Unix()
}
func(network *Network) SetNetworkLastModified(){
network.NetworkLastModified = time.Now().Unix()
func (network *Network) SetNetworkLastModified() {
network.NetworkLastModified = time.Now().Unix()
}
func(network *Network) SetDefaults(){
if network.DisplayName == "" {
network.DisplayName = network.NetID
}
if network.DefaultInterface == "" {
network.DefaultInterface = "nm-" + network.NetID
}
if network.DefaultListenPort == 0 {
network.DefaultListenPort = 51821
}
if network.DefaultPostDown == "" {
func (network *Network) SetDefaults() {
if network.DisplayName == "" {
network.DisplayName = network.NetID
}
if network.DefaultInterface == "" {
network.DefaultInterface = "nm-" + network.NetID
}
if network.DefaultListenPort == 0 {
network.DefaultListenPort = 51821
}
if network.DefaultPostDown == "" {
}
if network.DefaultSaveConfig == nil {
defaultsave := true
network.DefaultSaveConfig = &defaultsave
}
if network.DefaultKeepalive == 0 {
network.DefaultKeepalive = 20
}
if network.DefaultPostUp == "" {
}
//Check-In Interval for Nodes, In Seconds
if network.DefaultCheckInInterval == 0 {
network.DefaultCheckInInterval = 30
}
if network.AllowManualSignUp == nil {
signup := false
network.AllowManualSignUp = &signup
}
}
if network.DefaultSaveConfig == nil {
defaultsave := true
network.DefaultSaveConfig = &defaultsave
}
if network.DefaultKeepalive == 0 {
network.DefaultKeepalive = 20
}
if network.DefaultPostUp == "" {
}
//Check-In Interval for Nodes, In Seconds
if network.DefaultCheckInInterval == 0 {
network.DefaultCheckInInterval = 30
}
if network.AllowManualSignUp == nil {
signup := false
network.AllowManualSignUp = &signup
}
}