refactoring validation and models

This commit is contained in:
afeiszli
2021-07-23 18:24:34 -04:00
parent 93b0b94788
commit a982b62445
16 changed files with 363 additions and 415 deletions

View File

@@ -1,4 +1,4 @@
default k8scom tester textx comms { comms my-net one-more other-net {
reload 15s reload 15s
hosts /root/dnsconfig/netmaker.hosts { hosts /root/dnsconfig/netmaker.hosts {
fallthrough fallthrough

View File

@@ -0,0 +1 @@
10.10.0.12 node-nokdw.my-net

View File

@@ -54,6 +54,10 @@ func GetExtPeersList(networkName string, macaddress string) ([]models.ExtPeersRe
var peer models.ExtPeersResponse var peer models.ExtPeersResponse
var extClient models.ExtClient var extClient models.ExtClient
err = json.Unmarshal([]byte(value), &peer) err = json.Unmarshal([]byte(value), &peer)
if err != nil {
functions.PrintUserLog("netmaker", "failed to unmarshal peer", 2)
continue
}
err = json.Unmarshal([]byte(value), &extClient) err = json.Unmarshal([]byte(value), &extClient)
if err != nil { if err != nil {
functions.PrintUserLog("netmaker", "failed to unmarshal ext client", 2) functions.PrintUserLog("netmaker", "failed to unmarshal ext client", 2)
@@ -193,16 +197,13 @@ func UpdateNode(nodechange models.NodeUpdate, node models.Node) (models.Node, er
if err != nil { if err != nil {
return models.Node{}, err return models.Node{}, err
} }
err = database.Insert(newkey, string(value), database.NODES_TABLE_NAME) err = database.Insert(newkey, string(value), database.NODES_TABLE_NAME)
if notifynetwork { if notifynetwork {
err = SetNetworkNodesLastModified(node.Network) err = SetNetworkNodesLastModified(node.Network)
} }
if servercfg.IsDNSMode() { if servercfg.IsDNSMode() {
err = SetDNS() err = SetDNS()
} }
return node, err return node, err
} }

View File

@@ -59,7 +59,7 @@ func getAllDNS(w http.ResponseWriter, r *http.Request) {
func GetAllDNS() ([]models.DNSEntry, error) { func GetAllDNS() ([]models.DNSEntry, error) {
var dns []models.DNSEntry var dns []models.DNSEntry
networks, err := functions.ListNetworks() networks, err := models.GetNetworks()
if err != nil { if err != nil {
return []models.DNSEntry{}, err return []models.DNSEntry{}, err
} }
@@ -141,7 +141,7 @@ func GetCustomDNS(network string) ([]models.DNSEntry, error) {
func SetDNS() error { func SetDNS() error {
hostfile := txeh.Hosts{} hostfile := txeh.Hosts{}
var corefilestring string var corefilestring string
networks, err := functions.ListNetworks() networks, err := models.GetNetworks()
if err != nil { if err != nil {
return err return err
} }

View File

@@ -132,7 +132,7 @@ func getNetworks(w http.ResponseWriter, r *http.Request) {
allnetworks := []models.Network{} allnetworks := []models.Network{}
err := errors.New("Networks Error") err := errors.New("Networks Error")
if networksSlice[0] == ALL_NETWORK_ACCESS { if networksSlice[0] == ALL_NETWORK_ACCESS {
allnetworks, err = functions.ListNetworks() allnetworks, err = models.GetNetworks()
if err != nil { if err != nil {
returnErrorResponse(w, r, formatError(err, "internal")) returnErrorResponse(w, r, formatError(err, "internal"))
return return
@@ -166,7 +166,7 @@ func RemoveComms(networks []models.Network) []models.Network {
return append(returnable, networks[index+1:]...) return append(returnable, networks[index+1:]...)
} }
func ValidateNetworkUpdate(network models.NetworkUpdate) error { func ValidateNetworkUpdate(network models.Network) error {
v := validator.New() v := validator.New()
_ = v.RegisterValidation("netid_valid", func(fl validator.FieldLevel) bool { _ = v.RegisterValidation("netid_valid", func(fl validator.FieldLevel) bool {
@@ -177,71 +177,6 @@ func ValidateNetworkUpdate(network models.NetworkUpdate) error {
return inCharSet return inCharSet
}) })
// _ = v.RegisterValidation("addressrange_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())
// return isvalid
// })
// _ = v.RegisterValidation("netid_valid", func(fl validator.FieldLevel) bool {
// return true
// })
// _ = v.RegisterValidation("displayname_unique", func(fl validator.FieldLevel) bool {
// return true
// })
err := v.Struct(network)
if err != nil {
for _, e := range err.(validator.ValidationErrors) {
fmt.Println(e)
}
}
return err
}
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 {
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("netid_valid", func(fl validator.FieldLevel) bool {
isFieldUnique, _ := functions.IsNetworkNameUnique(fl.Field().String())
inCharSet := functions.NameInNetworkCharSet(fl.Field().String())
return isFieldUnique && inCharSet
})
//
_ = v.RegisterValidation("displayname_valid", func(fl validator.FieldLevel) bool {
isFieldUnique, _ := functions.IsNetworkDisplayNameUnique(fl.Field().String())
inCharSet := functions.NameInNetworkCharSet(fl.Field().String())
return isFieldUnique && inCharSet
})
err := v.Struct(network) err := v.Struct(network)
if err != nil { if err != nil {
@@ -341,33 +276,36 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) {
return return
} }
var networkChange models.NetworkUpdate var newNetwork models.Network
err = json.NewDecoder(r.Body).Decode(&newNetwork)
_ = json.NewDecoder(r.Body).Decode(&networkChange)
if networkChange.AddressRange == "" {
networkChange.AddressRange = network.AddressRange
}
if networkChange.AddressRange6 == "" {
networkChange.AddressRange6 = network.AddressRange6
}
if networkChange.NetID == "" {
networkChange.NetID = network.NetID
}
err = ValidateNetworkUpdate(networkChange)
if err != nil {
returnErrorResponse(w, r, formatError(err, "badrequest"))
return
}
returnednetwork, err := UpdateNetwork(networkChange, network)
if err != nil { if err != nil {
returnErrorResponse(w, r, formatError(err, "badrequest")) returnErrorResponse(w, r, formatError(err, "badrequest"))
return return
} }
rangeupdate, localrangeupdate, err := network.Update(&newNetwork)
if err != nil {
returnErrorResponse(w, r, formatError(err, "badrequest"))
return
}
if rangeupdate {
err = functions.UpdateNetworkNodeAddresses(network.NetID)
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
}
if localrangeupdate {
err = functions.UpdateNetworkLocalAddresses(network.NetID)
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
}
functions.PrintUserLog(r.Header.Get("user"), "updated network "+netname, 1) functions.PrintUserLog(r.Header.Get("user"), "updated network "+netname, 1)
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(returnednetwork) json.NewEncoder(w).Encode(newNetwork)
} }
func updateNetworkNodeLimit(w http.ResponseWriter, r *http.Request) { func updateNetworkNodeLimit(w http.ResponseWriter, r *http.Request) {
@@ -381,7 +319,7 @@ func updateNetworkNodeLimit(w http.ResponseWriter, r *http.Request) {
return return
} }
var networkChange models.NetworkUpdate var networkChange models.Network
_ = json.NewDecoder(r.Body).Decode(&networkChange) _ = json.NewDecoder(r.Body).Decode(&networkChange)
@@ -399,98 +337,6 @@ func updateNetworkNodeLimit(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(network) json.NewEncoder(w).Encode(network)
} }
func UpdateNetwork(networkChange models.NetworkUpdate, network models.Network) (models.Network, error) {
//NOTE: Network.NetID is intentionally NOT editable. It acts as a static ID for the network.
//DisplayName can be changed instead, which is what shows on the front end
if networkChange.NetID != network.NetID {
return models.Network{}, errors.New("NetID is not editable")
}
haschange := false
hasrangeupdate := false
haslocalrangeupdate := false
if networkChange.AddressRange != "" {
haschange = true
hasrangeupdate = true
network.AddressRange = networkChange.AddressRange
}
if networkChange.LocalRange != "" {
haschange = true
haslocalrangeupdate = true
network.LocalRange = networkChange.LocalRange
}
if networkChange.IsLocal != nil {
network.IsLocal = networkChange.IsLocal
}
if networkChange.IsDualStack != nil {
network.IsDualStack = networkChange.IsDualStack
}
if networkChange.DefaultListenPort != 0 {
network.DefaultListenPort = networkChange.DefaultListenPort
haschange = true
}
if networkChange.DefaultPostDown != "" {
network.DefaultPostDown = networkChange.DefaultPostDown
haschange = true
}
if networkChange.DefaultInterface != "" {
network.DefaultInterface = networkChange.DefaultInterface
haschange = true
}
if networkChange.DefaultPostUp != "" {
network.DefaultPostUp = networkChange.DefaultPostUp
haschange = true
}
if networkChange.DefaultKeepalive != 0 {
network.DefaultKeepalive = networkChange.DefaultKeepalive
haschange = true
}
if networkChange.DisplayName != "" {
network.DisplayName = networkChange.DisplayName
haschange = true
}
if networkChange.DefaultCheckInInterval != 0 {
network.DefaultCheckInInterval = networkChange.DefaultCheckInInterval
haschange = true
}
if networkChange.AllowManualSignUp != nil {
network.AllowManualSignUp = networkChange.AllowManualSignUp
haschange = true
}
if haschange {
network.SetNetworkLastModified()
}
data, err := json.Marshal(&network)
if err != nil {
return models.Network{}, err
}
database.Insert(network.NetID, string(data), database.NETWORKS_TABLE_NAME)
//Cycles through nodes and gives them new IP's based on the new range
//Pretty cool, but also pretty inefficient currently
if hasrangeupdate {
err = functions.UpdateNetworkNodeAddresses(network.NetID)
if err != nil {
return models.Network{}, err
}
}
if haslocalrangeupdate {
err = functions.UpdateNetworkLocalAddresses(network.NetID)
if err != nil {
return models.Network{}, err
}
}
returnnetwork, err := functions.GetParentNetwork(network.NetID)
if err != nil {
return models.Network{}, err
}
return returnnetwork, nil
}
//Delete a network //Delete a network
//Will stop you if there's any nodes associated //Will stop you if there's any nodes associated
func deleteNetwork(w http.ResponseWriter, r *http.Request) { func deleteNetwork(w http.ResponseWriter, r *http.Request) {
@@ -553,28 +399,18 @@ func createNetwork(w http.ResponseWriter, r *http.Request) {
} }
func CreateNetwork(network models.Network) error { 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
if network.IsLocal == nil {
falsevar := false
network.IsLocal = &falsevar
}
if network.IsDualStack == nil {
falsevar := false
network.IsDualStack = &falsevar
}
err := ValidateNetworkCreate(network)
if err != nil {
//returnErrorResponse(w, r, formatError(err, "badrequest"))
return err
}
network.SetDefaults() network.SetDefaults()
network.SetNodesLastModified() network.SetNodesLastModified()
network.SetNetworkLastModified() network.SetNetworkLastModified()
network.KeyUpdateTimeStamp = time.Now().Unix() network.KeyUpdateTimeStamp = time.Now().Unix()
err := network.Validate()
if err != nil {
//returnErrorResponse(w, r, formatError(err, "badrequest"))
return err
}
data, err := json.Marshal(&network) data, err := json.Marshal(&network)
if err != nil { if err != nil {
return err return err
@@ -611,7 +447,7 @@ func createAccessKey(w http.ResponseWriter, r *http.Request) {
returnErrorResponse(w, r, formatError(err, "badrequest")) returnErrorResponse(w, r, formatError(err, "badrequest"))
return return
} }
functions.PrintUserLog(r.Header.Get("user"), "created access key "+netname, 1) functions.PrintUserLog(r.Header.Get("user"), "created access key "+accesskey.Name+" on "+netname, 1)
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(key) json.NewEncoder(w).Encode(key)
//w.Write([]byte(accesskey.AccessString)) //w.Write([]byte(accesskey.AccessString))
@@ -641,11 +477,9 @@ func CreateAccessKey(accesskey models.AccessKey, network models.Network) (models
} }
} }
privAddr := "" privAddr := ""
if network.IsLocal != nil { if network.IsLocal != "" {
if *network.IsLocal {
privAddr = network.LocalRange privAddr = network.LocalRange
} }
}
netID := network.NetID netID := network.NetID

View File

@@ -30,7 +30,7 @@ func deleteNet(t *testing.T) {
err := DeleteDNS(entry.Name, entry.Network) err := DeleteDNS(entry.Name, entry.Network)
assert.Nil(t, err) assert.Nil(t, err)
} }
networks, _ := functions.ListNetworks() networks, _ := models.GetNetworks()
for _, network := range networks { for _, network := range networks {
t.Log("deleting network", network.NetID) t.Log("deleting network", network.NetID)
success, err := DeleteNetwork(network.NetID) success, err := DeleteNetwork(network.NetID)
@@ -54,7 +54,7 @@ func getNet() models.Network {
} }
func TestGetNetworks(t *testing.T) { func TestGetNetworks(t *testing.T) {
//calls functions.ListNetworks --- nothing to be done //calls models.GetNetworks --- nothing to be done
} }
func TestCreateNetwork(t *testing.T) { func TestCreateNetwork(t *testing.T) {
deleteNet(t) deleteNet(t)
@@ -108,14 +108,14 @@ func TestUpdateNetwork(t *testing.T) {
createNet() createNet()
network := getNet() network := getNet()
t.Run("NetID", func(t *testing.T) { t.Run("NetID", func(t *testing.T) {
var networkupdate models.NetworkUpdate var networkupdate models.Network
networkupdate.NetID = "wirecat" networkupdate.NetID = "wirecat"
_, err := UpdateNetwork(networkupdate, network) _, err := UpdateNetwork(networkupdate, network)
assert.NotNil(t, err) assert.NotNil(t, err)
assert.Equal(t, "NetID is not editable", err.Error()) assert.Equal(t, "NetID is not editable", err.Error())
}) })
t.Run("LocalRange", func(t *testing.T) { t.Run("LocalRange", func(t *testing.T) {
var networkupdate models.NetworkUpdate var networkupdate models.Network
//NetID needs to be set as it will be in updateNetwork //NetID needs to be set as it will be in updateNetwork
networkupdate.NetID = "skynet" networkupdate.NetID = "skynet"
networkupdate.LocalRange = "192.168.0.1/24" networkupdate.LocalRange = "192.168.0.1/24"
@@ -372,7 +372,7 @@ func TestValidateNetworkUpdate(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
t.Run(tc.testname, func(t *testing.T) { t.Run(tc.testname, func(t *testing.T) {
network := models.NetworkUpdate(tc.network) network := models.Network(tc.network)
err := ValidateNetworkUpdate(network) err := ValidateNetworkUpdate(network)
assert.NotNil(t, err) assert.NotNil(t, err)
assert.Contains(t, err.Error(), tc.errMessage) assert.Contains(t, err.Error(), tc.errMessage)

View File

@@ -34,14 +34,6 @@ func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.ReadNodeRe
} }
*/ */
// Cast to ReadNodeRes type // Cast to ReadNodeRes type
dualvar := false
if network.IsDualStack != nil {
dualvar = *network.IsDualStack
}
localvar := false
if network.IsLocal != nil {
localvar = *network.IsLocal
}
response := &nodepb.ReadNodeRes{ response := &nodepb.ReadNodeRes{
Node: &nodepb.Node{ Node: &nodepb.Node{
@@ -64,8 +56,8 @@ func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.ReadNodeRe
Publickey: node.PublicKey, Publickey: node.PublicKey,
Listenport: node.ListenPort, Listenport: node.ListenPort,
Keepalive: node.PersistentKeepalive, Keepalive: node.PersistentKeepalive,
Islocal: localvar, Islocal: network.IsLocal == "yes",
Isdualstack: dualvar, Isdualstack: network.IsDualStack == "yes",
Localrange: network.LocalRange, Localrange: network.LocalRange,
}, },
} }
@@ -165,7 +157,7 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
if !validKey { if !validKey {
//Check to see if network will allow manual sign up //Check to see if network will allow manual sign up
//may want to switch this up with the valid key check and avoid a DB call that way. //may want to switch this up with the valid key check and avoid a DB call that way.
if *network.AllowManualSignUp { if network.AllowManualSignUp == "yes" {
node.IsPending = true node.IsPending = true
} else { } else {
return nil, status.Errorf( return nil, status.Errorf(
@@ -184,14 +176,6 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
fmt.Sprintf("Internal error: %v", err), fmt.Sprintf("Internal error: %v", err),
) )
} }
dualvar := false
if network.IsDualStack != nil {
dualvar = *network.IsDualStack
}
localvar := false
if network.IsLocal != nil {
localvar = *network.IsLocal
}
// return the node in a CreateNodeRes type // return the node in a CreateNodeRes type
response := &nodepb.CreateNodeRes{ response := &nodepb.CreateNodeRes{
@@ -210,8 +194,8 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
Publickey: node.PublicKey, Publickey: node.PublicKey,
Listenport: node.ListenPort, Listenport: node.ListenPort,
Keepalive: node.PersistentKeepalive, Keepalive: node.PersistentKeepalive,
Islocal: localvar, Islocal: network.IsLocal == "yes",
Isdualstack: dualvar, Isdualstack: network.IsDualStack == "yes",
Localrange: network.LocalRange, Localrange: network.LocalRange,
}, },
} }
@@ -318,15 +302,6 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNo
fmt.Sprintf("Could not find node with supplied Mac Address: %v", err), fmt.Sprintf("Could not find node with supplied Mac Address: %v", err),
) )
} }
dualvar := false
if network.IsDualStack != nil {
dualvar = *network.IsDualStack
}
localvar := false
if network.IsLocal != nil {
localvar = *network.IsLocal
}
return &nodepb.UpdateNodeRes{ return &nodepb.UpdateNodeRes{
Node: &nodepb.Node{ Node: &nodepb.Node{
Macaddress: newnode.MacAddress, Macaddress: newnode.MacAddress,
@@ -345,8 +320,8 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNo
Dnsoff: !servercfg.IsDNSMode(), Dnsoff: !servercfg.IsDNSMode(),
Listenport: newnode.ListenPort, Listenport: newnode.ListenPort,
Keepalive: newnode.PersistentKeepalive, Keepalive: newnode.PersistentKeepalive,
Islocal: localvar, Islocal: network.IsLocal == "yes",
Isdualstack: dualvar, Isdualstack: network.IsDualStack == "yes",
Localrange: network.LocalRange, Localrange: network.LocalRange,
}, },
}, nil }, nil

View File

@@ -17,17 +17,17 @@ import (
func nodeHandlers(r *mux.Router) { func nodeHandlers(r *mux.Router) {
r.HandleFunc("/api/nodes", authorize(false, "master", http.HandlerFunc(getAllNodes))).Methods("GET") r.HandleFunc("/api/nodes", authorize(false, "user", http.HandlerFunc(getAllNodes))).Methods("GET")
r.HandleFunc("/api/nodes/{network}", authorize(true, "network", http.HandlerFunc(getNetworkNodes))).Methods("GET") r.HandleFunc("/api/nodes/{network}", authorize(true, "network", http.HandlerFunc(getNetworkNodes))).Methods("GET")
r.HandleFunc("/api/nodes/{network}/{macaddress}", authorize(true, "node", http.HandlerFunc(getNode))).Methods("GET") r.HandleFunc("/api/nodes/{network}/{macaddress}", authorize(true, "node", http.HandlerFunc(getNode))).Methods("GET")
r.HandleFunc("/api/nodes/{network}/{macaddress}", authorize(true, "node", http.HandlerFunc(updateNode))).Methods("PUT") r.HandleFunc("/api/nodes/{network}/{macaddress}", authorize(true, "node", http.HandlerFunc(updateNode))).Methods("PUT")
r.HandleFunc("/api/nodes/{network}/{macaddress}", authorize(true, "node", http.HandlerFunc(deleteNode))).Methods("DELETE") r.HandleFunc("/api/nodes/{network}/{macaddress}", authorize(true, "node", http.HandlerFunc(deleteNode))).Methods("DELETE")
r.HandleFunc("/api/nodes/{network}/{macaddress}/checkin", authorize(true, "node", http.HandlerFunc(checkIn))).Methods("POST") r.HandleFunc("/api/nodes/{network}/{macaddress}/checkin", authorize(true, "node", http.HandlerFunc(checkIn))).Methods("POST")
r.HandleFunc("/api/nodes/{network}/{macaddress}/creategateway", authorize(true, "master", http.HandlerFunc(createEgressGateway))).Methods("POST") r.HandleFunc("/api/nodes/{network}/{macaddress}/creategateway", authorize(true, "user", http.HandlerFunc(createEgressGateway))).Methods("POST")
r.HandleFunc("/api/nodes/{network}/{macaddress}/deletegateway", authorize(true, "master", http.HandlerFunc(deleteEgressGateway))).Methods("DELETE") r.HandleFunc("/api/nodes/{network}/{macaddress}/deletegateway", authorize(true, "user", http.HandlerFunc(deleteEgressGateway))).Methods("DELETE")
r.HandleFunc("/api/nodes/{network}/{macaddress}/createingress", securityCheck(false, http.HandlerFunc(createIngressGateway))).Methods("POST") r.HandleFunc("/api/nodes/{network}/{macaddress}/createingress", securityCheck(false, http.HandlerFunc(createIngressGateway))).Methods("POST")
r.HandleFunc("/api/nodes/{network}/{macaddress}/deleteingress", securityCheck(false, http.HandlerFunc(deleteIngressGateway))).Methods("DELETE") r.HandleFunc("/api/nodes/{network}/{macaddress}/deleteingress", securityCheck(false, http.HandlerFunc(deleteIngressGateway))).Methods("DELETE")
r.HandleFunc("/api/nodes/{network}/{macaddress}/approve", authorize(true, "master", http.HandlerFunc(uncordonNode))).Methods("POST") r.HandleFunc("/api/nodes/{network}/{macaddress}/approve", authorize(true, "user", http.HandlerFunc(uncordonNode))).Methods("POST")
r.HandleFunc("/api/nodes/{network}", createNode).Methods("POST") r.HandleFunc("/api/nodes/{network}", createNode).Methods("POST")
r.HandleFunc("/api/nodes/adm/{network}/lastmodified", authorize(true, "network", http.HandlerFunc(getLastModified))).Methods("GET") r.HandleFunc("/api/nodes/adm/{network}/lastmodified", authorize(true, "network", http.HandlerFunc(getLastModified))).Methods("GET")
r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods("POST") r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods("POST")
@@ -147,7 +147,6 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
//TODO: Consider better RBAC implementations //TODO: Consider better RBAC implementations
func authorize(networkCheck bool, authNetwork string, next http.Handler) http.HandlerFunc { func authorize(networkCheck bool, authNetwork string, next http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
var errorResponse = models.ErrorResponse{ var errorResponse = models.ErrorResponse{
Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.", Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
} }
@@ -155,7 +154,6 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha
var params = mux.Vars(r) var params = mux.Vars(r)
networkexists, _ := functions.NetworkExists(params["network"]) networkexists, _ := functions.NetworkExists(params["network"])
//check that the request is for a valid network //check that the request is for a valid network
//if (networkCheck && !networkexists) || err != nil { //if (networkCheck && !networkexists) || err != nil {
if networkCheck && !networkexists { if networkCheck && !networkexists {
@@ -164,9 +162,7 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha
} }
returnErrorResponse(w, r, errorResponse) returnErrorResponse(w, r, errorResponse)
return return
} else { } else {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
//get the auth token //get the auth token
@@ -192,7 +188,6 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha
//A: the token is the master password //A: the token is the master password
//B: the token corresponds to a mac address, and if so, which one //B: the token corresponds to a mac address, and if so, which one
//TODO: There's probably a better way of dealing with the "master token"/master password. Plz Halp. //TODO: There's probably a better way of dealing with the "master token"/master password. Plz Halp.
var isAuthorized = false var isAuthorized = false
var macaddress = "" var macaddress = ""
username, networks, isadmin, errN := functions.VerifyUserToken(authToken) username, networks, isadmin, errN := functions.VerifyUserToken(authToken)
@@ -219,7 +214,6 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha
//The mastermac (login with masterkey from config) can do everything!! May be dangerous. //The mastermac (login with masterkey from config) can do everything!! May be dangerous.
if macaddress == "mastermac" { if macaddress == "mastermac" {
isAuthorized = true isAuthorized = true
//for everyone else, there's poor man's RBAC. The "cases" are defined in the routes in the handlers //for everyone else, there's poor man's RBAC. The "cases" are defined in the routes in the handlers
//So each route defines which access network should be allowed to access it //So each route defines which access network should be allowed to access it
} else { } else {
@@ -248,8 +242,8 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha
} else { } else {
isAuthorized = (macaddress == params["macaddress"]) isAuthorized = (macaddress == params["macaddress"])
} }
case "master": case "user":
isAuthorized = (macaddress == "mastermac") isAuthorized = true
default: default:
isAuthorized = false isAuthorized = false
} }
@@ -316,7 +310,7 @@ func GetNetworkNodes(network string) ([]models.Node, error) {
//Not quite sure if this is necessary. Probably necessary based on front end but may want to review after iteration 1 if it's being used or not //Not quite sure if this is necessary. Probably necessary based on front end but may want to review after iteration 1 if it's being used or not
func getAllNodes(w http.ResponseWriter, r *http.Request) { func getAllNodes(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
nodes, err := functions.GetAllNodes() nodes, err := getUsersNodes(r.Header.Get("user"))
if err != nil { if err != nil {
returnErrorResponse(w, r, formatError(err, "internal")) returnErrorResponse(w, r, formatError(err, "internal"))
return return
@@ -327,6 +321,22 @@ func getAllNodes(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(nodes) json.NewEncoder(w).Encode(nodes)
} }
func getUsersNodes(username string) ([]models.Node, error) {
var nodes []models.Node
user, err := functions.GetUser(username)
if err != nil {
return nodes, err
}
for _, networkName := range user.Networks {
tmpNodes, err := GetNetworkNodes(networkName)
if err != nil {
continue
}
nodes = append(nodes, tmpNodes...)
}
return nodes, err
}
//This function get's called when a node "checks in" at check in interval //This function get's called when a node "checks in" at check in interval
//Honestly I'm not sure what all it should be doing //Honestly I'm not sure what all it should be doing
//TODO: Implement the necessary stuff, including the below //TODO: Implement the necessary stuff, including the below
@@ -460,7 +470,7 @@ func createNode(w http.ResponseWriter, r *http.Request) {
if !validKey { if !validKey {
//Check to see if network will allow manual sign up //Check to see if network will allow manual sign up
//may want to switch this up with the valid key check and avoid a DB call that way. //may want to switch this up with the valid key check and avoid a DB call that way.
if *network.AllowManualSignUp { if network.AllowManualSignUp == "yes" {
node.IsPending = true node.IsPending = true
} else { } else {
errorResponse = models.ErrorResponse{ errorResponse = models.ErrorResponse{
@@ -678,6 +688,7 @@ func CreateIngressGateway(netid string, macaddress string) (models.Node, error)
log.Println("Could not find network.") log.Println("Could not find network.")
return models.Node{}, err return models.Node{}, err
} }
node.IsIngressGateway = true
node.IngressGatewayRange = network.AddressRange node.IngressGatewayRange = network.AddressRange
postUpCmd := "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE" postUpCmd := "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE"
postDownCmd := "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE" postDownCmd := "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE"
@@ -748,6 +759,7 @@ func DeleteIngressGateway(network, macaddress string) (models.Node, error) {
} }
func updateNode(w http.ResponseWriter, r *http.Request) { func updateNode(w http.ResponseWriter, r *http.Request) {
log.Println("update reached.")
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
var params = mux.Vars(r) var params = mux.Vars(r)
@@ -756,7 +768,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
//id, _ := primitive.ObjectIDFromHex(params["id"]) //id, _ := primitive.ObjectIDFromHex(params["id"])
var node models.Node var node models.Node
log.Println("Called", params["network"], params["macaddress"])
//start here //start here
node, err := functions.GetNodeByMacAddress(params["network"], params["macaddress"]) node, err := functions.GetNodeByMacAddress(params["network"], params["macaddress"])
if err != nil { if err != nil {

View File

@@ -152,7 +152,6 @@ func authorizeUserAdm(next http.Handler) http.HandlerFunc {
func ValidateUserToken(token string, user string, adminonly bool) error { func ValidateUserToken(token string, user string, adminonly bool) error {
var tokenSplit = strings.Split(token, " ") var tokenSplit = strings.Split(token, " ")
//I put this in in case the user doesn't put in a token at all (in which case it's empty) //I put this in in case the user doesn't put in a token at all (in which case it's empty)
//There's probably a smarter way of handling this. //There's probably a smarter way of handling this.
var authToken = "928rt238tghgwe@TY@$Y@#WQAEGB2FC#@HG#@$Hddd" var authToken = "928rt238tghgwe@TY@$Y@#WQAEGB2FC#@HG#@$Hddd"
@@ -213,7 +212,20 @@ func hasAdmin(w http.ResponseWriter, r *http.Request) {
} }
func GetUser(username string) (models.User, error) { func GetUser(username string) (models.ReturnUser, error) {
var user models.ReturnUser
record, err := database.FetchRecord(database.USERS_TABLE_NAME, username)
if err != nil {
return user, err
}
if err = json.Unmarshal([]byte(record), &user); err != nil {
return models.ReturnUser{}, err
}
return user, err
}
func GetUserInternal(username string) (models.User, error) {
var user models.User var user models.User
record, err := database.FetchRecord(database.USERS_TABLE_NAME, username) record, err := database.FetchRecord(database.USERS_TABLE_NAME, username)
@@ -226,9 +238,9 @@ func GetUser(username string) (models.User, error) {
return user, err return user, err
} }
func GetUsers() ([]models.User, error) { func GetUsers() ([]models.ReturnUser, error) {
var users []models.User var users []models.ReturnUser
collection, err := database.FetchRecords(database.USERS_TABLE_NAME) collection, err := database.FetchRecords(database.USERS_TABLE_NAME)
@@ -238,7 +250,7 @@ func GetUsers() ([]models.User, error) {
for _, value := range collection { for _, value := range collection {
var user models.User var user models.ReturnUser
err = json.Unmarshal([]byte(value), &user) err = json.Unmarshal([]byte(value), &user)
if err != nil { if err != nil {
continue // get users continue // get users
@@ -394,7 +406,7 @@ func updateUser(w http.ResponseWriter, r *http.Request) {
var user models.User var user models.User
//start here //start here
username := params["username"] username := params["username"]
user, err := GetUser(username) user, err := GetUserInternal(username)
if err != nil { if err != nil {
returnErrorResponse(w, r, formatError(err, "internal")) returnErrorResponse(w, r, formatError(err, "internal"))
return return
@@ -422,7 +434,7 @@ func updateUserAdm(w http.ResponseWriter, r *http.Request) {
var user models.User var user models.User
//start here //start here
username := params["username"] username := params["username"]
user, err := GetUser(username) user, err := GetUserInternal(username)
if err != nil { if err != nil {
returnErrorResponse(w, r, formatError(err, "internal")) returnErrorResponse(w, r, formatError(err, "internal"))
return return
@@ -445,6 +457,10 @@ func updateUserAdm(w http.ResponseWriter, r *http.Request) {
func DeleteUser(user string) (bool, error) { func DeleteUser(user string) (bool, error) {
if userRecord, err := database.FetchRecord(database.USERS_TABLE_NAME, user); err != nil || len(userRecord) == 0 {
return false, errors.New("user does not exist")
}
err := database.DeleteRecord(database.USERS_TABLE_NAME, user) err := database.DeleteRecord(database.USERS_TABLE_NAME, user)
if err != nil { if err != nil {
return false, err return false, err
@@ -466,7 +482,7 @@ func deleteUser(w http.ResponseWriter, r *http.Request) {
returnErrorResponse(w, r, formatError(err, "internal")) returnErrorResponse(w, r, formatError(err, "internal"))
return return
} else if !success { } else if !success {
returnErrorResponse(w, r, formatError(errors.New("Delete unsuccessful."), "badrequest")) returnErrorResponse(w, r, formatError(errors.New("delete unsuccessful."), "badrequest"))
return return
} }

View File

@@ -93,5 +93,6 @@ func FetchRecords(tableName string) (map[string]string, error) {
row.Scan(&key, &value) row.Scan(&key, &value)
records[key] = value records[key] = value
} }
// log.Println(records)
return records, nil return records, nil
} }

View File

@@ -54,6 +54,19 @@ func ParseIntClient(value string) (models.IntClient, error) {
//Takes in an arbitrary field and value for field and checks to see if any other //Takes in an arbitrary field and value for field and checks to see if any other
//node has that value for the same field within the network //node has that value for the same field within the network
func GetUser(username string) (models.User, error) {
var user models.User
record, err := database.FetchRecord(database.USERS_TABLE_NAME, username)
if err != nil {
return user, err
}
if err = json.Unmarshal([]byte(record), &user); err != nil {
return models.User{}, err
}
return user, err
}
func SliceContains(slice []string, item string) bool { func SliceContains(slice []string, item string) bool {
set := make(map[string]struct{}, len(slice)) set := make(map[string]struct{}, len(slice))
for _, s := range slice { for _, s := range slice {
@@ -252,32 +265,11 @@ func UpdateNetworkLocalAddresses(networkName string) error {
return nil return nil
} }
//Checks to see if any other networks have the same name (id)
func IsNetworkNameUnique(name string) (bool, error) {
isunique := true
dbs, err := ListNetworks()
if err != nil {
return false, err
}
for i := 0; i < len(dbs); i++ {
if name == dbs[i].NetID {
isunique = false
}
}
return isunique, nil
}
func IsNetworkDisplayNameUnique(name string) (bool, error) { func IsNetworkDisplayNameUnique(name string) (bool, error) {
isunique := true isunique := true
dbs, err := ListNetworks() dbs, err := models.GetNetworks()
if err != nil { if err != nil {
return false, err return false, err
} }
@@ -333,30 +325,6 @@ func GetNetworkNodeNumber(networkName string) (int, error) {
return count, nil return count, nil
} }
// Anyway, returns all the networks
func ListNetworks() ([]models.Network, error) {
var networks []models.Network
collection, err := database.FetchRecords(database.NETWORKS_TABLE_NAME)
if err != nil {
return networks, err
}
for _, value := range collection {
var network models.Network
if err := json.Unmarshal([]byte(value), &network); err != nil {
return networks, err
}
// add network our array
networks = append(networks, network)
}
return networks, err
}
//Checks to see if access key is valid //Checks to see if access key is valid
//Does so by checking against all keys and seeing if any have the same value //Does so by checking against all keys and seeing if any have the same value
//may want to hash values before comparing...consider this //may want to hash values before comparing...consider this
@@ -385,7 +353,7 @@ func IsKeyValid(networkname string, keyvalue string) bool {
func IsKeyValidGlobal(keyvalue string) bool { func IsKeyValidGlobal(keyvalue string) bool {
networks, _ := ListNetworks() networks, _ := models.GetNetworks()
var key models.AccessKey var key models.AccessKey
foundkey := false foundkey := false
isvalid := false isvalid := false
@@ -499,20 +467,21 @@ func GetNodeByMacAddress(network string, macaddress string) (models.Node, error)
var node models.Node var node models.Node
records, err := database.FetchRecords(database.NODES_TABLE_NAME) key, err := GetRecordKey(macaddress, network)
if err != nil { if err != nil {
return node, err return node, err
} }
for _, value := range records { record, err := database.FetchRecord(database.NODES_TABLE_NAME, key)
json.Unmarshal([]byte(value), &node) if err != nil {
if node.MacAddress == macaddress && node.Network == network { return models.Node{}, err
return node, nil
}
} }
return models.Node{}, nil if err = json.Unmarshal([]byte(record), &node); err != nil {
return models.Node{}, err
}
return node, nil
} }
func DeleteAllIntClients() error { func DeleteAllIntClients() error {
@@ -614,7 +583,7 @@ func UniqueAddress6(networkName string) (string, error) {
fmt.Println("Network Not Found") fmt.Println("Network Not Found")
return "", err return "", err
} }
if network.IsDualStack == nil || *network.IsDualStack == false { if network.IsDualStack == "no" {
if networkName != "comms" { if networkName != "comms" {
return "", nil return "", nil
} }

View File

@@ -1,73 +1,183 @@
package models package models
import ( import (
"encoding/json"
"errors"
"strings"
"time" "time"
"go.mongodb.org/mongo-driver/bson/primitive" "github.com/go-playground/validator/v10"
"github.com/gravitl/netmaker/database"
) )
//Network Struct //Network Struct
//At some point, need to replace all instances of Name with something else like Identifier //At some point, need to replace all instances of Name with something else like Identifier
type Network struct { type Network struct {
ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"`
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 AddressRange6 string `json:"addressrange6" bson:"addressrange6" validate:"regexp=^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$"`
// AddressRange6 string `json:"addressrange6" bson:"addressrange6" validate:"required_with=isdualstack true,cidrv6"`
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,min=1,max=20,displayname_valid"` DisplayName string `json:"displayname,omitempty" bson:"displayname,omitempty" validate:"omitempty,min=1,max=20,displayname_valid"`
NetID string `json:"netid" bson:"netid" validate:"required,min=1,max=12,netid_valid"` NetID string `json:"netid" bson:"netid" validate:"required,min=1,max=12,netid_valid"`
NodesLastModified int64 `json:"nodeslastmodified" bson:"nodeslastmodified"` NodesLastModified int64 `json:"nodeslastmodified" bson:"nodeslastmodified"`
NetworkLastModified int64 `json:"networklastmodified" bson:"networklastmodified"` NetworkLastModified int64 `json:"networklastmodified" bson:"networklastmodified"`
DefaultInterface string `json:"defaultinterface" bson:"defaultinterface"` DefaultInterface string `json:"defaultinterface" bson:"defaultinterface" validate:"min=1,max=15"`
DefaultListenPort int32 `json:"defaultlistenport,omitempty" bson:"defaultlistenport,omitempty" validate:"omitempty,min=1024,max=65535"` DefaultListenPort int32 `json:"defaultlistenport,omitempty" bson:"defaultlistenport,omitempty" validate:"omitempty,min=1024,max=65535"`
NodeLimit int32 `json:"nodelimit" bson:"nodelimit"` NodeLimit int32 `json:"nodelimit" bson:"nodelimit"`
DefaultPostUp string `json:"defaultpostup" bson:"defaultpostup"` DefaultPostUp string `json:"defaultpostup" bson:"defaultpostup"`
DefaultPostDown string `json:"defaultpostdown" bson:"defaultpostdown"` DefaultPostDown string `json:"defaultpostdown" bson:"defaultpostdown"`
KeyUpdateTimeStamp int64 `json:"keyupdatetimestamp" bson:"keyupdatetimestamp"` KeyUpdateTimeStamp int64 `json:"keyupdatetimestamp" bson:"keyupdatetimestamp"`
DefaultKeepalive int32 `json:"defaultkeepalive" bson:"defaultkeepalive" validate:"omitempty,max=1000"` DefaultKeepalive int32 `json:"defaultkeepalive" bson:"defaultkeepalive" validate:"omitempty,max=1000"`
DefaultSaveConfig *bool `json:"defaultsaveconfig" bson:"defaultsaveconfig"` DefaultSaveConfig string `json:"defaultsaveconfig" bson:"defaultsaveconfig" validate:"regexp=^(yes|no)$"`
AccessKeys []AccessKey `json:"accesskeys" bson:"accesskeys"` AccessKeys []AccessKey `json:"accesskeys" bson:"accesskeys"`
AllowManualSignUp *bool `json:"allowmanualsignup" bson:"allowmanualsignup"` AllowManualSignUp string `json:"allowmanualsignup" bson:"allowmanualsignup" validate:"regexp=^(yes|no)$"`
IsLocal *bool `json:"islocal" bson:"islocal"` IsLocal string `json:"islocal" bson:"islocal" validate:"regexp=^(yes|no)$"`
IsDualStack *bool `json:"isdualstack" bson:"isdualstack"` IsDualStack string `json:"isdualstack" bson:"isdualstack" validate:"regexp=^(yes|no)$"`
IsIPv4 string `json:"isipv4" bson:"isipv4"` IsIPv4 string `json:"isipv4" bson:"isipv4" validate:"regexp=^(yes|no)$"`
IsIPv6 string `json:"isipv6" bson:"isipv6"` IsIPv6 string `json:"isipv6" bson:"isipv6" validate:"regexp=^(yes|no)$"`
IsGRPCHub string `json:"isgrpchub" bson:"isgrpchub"` IsGRPCHub string `json:"isgrpchub" bson:"isgrpchub" validate:"regexp=^(yes|no)$"`
LocalRange string `json:"localrange" bson:"localrange" validate:"omitempty,cidr"` 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"` DefaultCheckInInterval int32 `json:"checkininterval,omitempty" bson:"checkininterval,omitempty" validate:"omitempty,numeric,min=2,max=100000"`
DefaultUDPHolePunch string `json:"defaultudpholepunch" bson:"defaultudpholepunch" validate:"regexp=^(yes|no)$"`
} }
type NetworkUpdate struct {
ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"`
AddressRange string `json:"addressrange" bson:"addressrange" validate:"omitempty,cidr"`
// bug in validator --- required_with does not work with bools issue#683 type SaveData struct { // put sensitive fields here
// AddressRange6 string `json:"addressrange6" bson:"addressrange6" validate:"required_with=isdualstack true,cidrv6"` NetID string `json:"netid" bson:"netid" validate:"required,min=1,max=12,netid_valid"`
AddressRange6 string `json:"addressrange6" bson:"addressrange6" validate:"omitempty,cidr"` }
//can't have min=1 with omitempty
DisplayName string `json:"displayname,omitempty" bson:"displayname,omitempty" validate:"omitempty,netid_valid,min=1,max=20"` var FIELDS = map[string][]string{
NetID string `json:"netid" bson:"netid" validate:"omitempty,netid_valid,min=1,max=15"` // "id": {"ID", "string"},
NodesLastModified int64 `json:"nodeslastmodified" bson:"nodeslastmodified"` "addressrange": {"AddressRange", "string"},
NetworkLastModified int64 `json:"networklastmodified" bson:"networklastmodified"` "addressrange6": {"AddressRange6", "string"},
DefaultInterface string `json:"defaultinterface" bson:"defaultinterface"` "displayname": {"DisplayName", "string"},
DefaultListenPort int32 `json:"defaultlistenport,omitempty" bson:"defaultlistenport,omitempty" validate:"omitempty,min=1024,max=65535"` "netid": {"NetID", "string"},
NodeLimit int32 `json:"nodelimit" bson:"nodelimit"` "nodeslastmodified": {"NodesLastModified", "int64"},
DefaultPostUp string `json:"defaultpostup" bson:"defaultpostup"` "networklastmodified": {"NetworkLastModified", "int64"},
DefaultPostDown string `json:"defaultpostdown" bson:"defaultpostdown"` "defaultinterface": {"DefaultInterface", "string"},
KeyUpdateTimeStamp int64 `json:"keyupdatetimestamp" bson:"keyupdatetimestamp"` "defaultlistenport": {"DefaultListenPort", "int32"},
DefaultKeepalive int32 `json:"defaultkeepalive" bson:"defaultkeepalive" validate:"omitempty,max=1000"` "nodelimit": {"NodeLimit", "int32"},
DefaultSaveConfig *bool `json:"defaultsaveconfig" bson:"defaultsaveconfig"` "defaultpostup": {"DefaultPostUp", "string"},
AccessKeys []AccessKey `json:"accesskeys" bson:"accesskeys"` "defaultpostdown": {"DefaultPostDown", "string"},
AllowManualSignUp *bool `json:"allowmanualsignup" bson:"allowmanualsignup"` "keyupdatetimestamp": {"KeyUpdateTimeStamp", "int64"},
IsLocal *bool `json:"islocal" bson:"islocal"` "defaultkeepalive": {"DefaultKeepalive", "int32"},
IsDualStack *bool `json:"isdualstack" bson:"isdualstack"` "defaultsaveconfig": {"DefaultSaveConfig", "string"},
IsIPv4 string `json:"isipv4" bson:"isipv4"` "accesskeys": {"AccessKeys", "[]AccessKey"},
IsIPv6 string `json:"isipv6" bson:"isipv6"` "allowmanualsignup": {"AllowManualSignUp", "string"},
IsGRPCHub string `json:"isgrpchub" bson:"isgrpchub"` "islocal": {"IsLocal", "string"},
LocalRange string `json:"localrange" bson:"localrange" validate:"omitempty,cidr"` "isdualstack": {"IsDualStack", "string"},
//can't have min=1 with omitempty "isipv4": {"IsIPv4", "string"},
DefaultCheckInInterval int32 `json:"checkininterval,omitempty" bson:"checkininterval,omitempty" validate:"omitempty,numeric,min=2,max=100000"` "isipv6": {"IsIPv6", "string"},
"isgrpchub": {"IsGRPCHub", "string"},
"localrange": {"LocalRange", "string"},
"checkininterval": {"DefaultCheckInInterval", "int32"},
"defaultudpholepunch": {"DefaultUDPHolePunch", "string"},
}
func (network *Network) FieldExists(field string) bool {
return len(FIELDS[field]) > 0
}
func (network *Network) NetIDInNetworkCharSet() bool {
charset := "abcdefghijklmnopqrstuvwxyz1234567890-_."
for _, char := range network.NetID {
if !strings.Contains(charset, strings.ToLower(string(char))) {
return false
}
}
return true
}
func (network *Network) DisplayNameInNetworkCharSet() bool {
charset := "abcdefghijklmnopqrstuvwxyz1234567890-_./;% ^#()!@$*"
for _, char := range network.DisplayName {
if !strings.Contains(charset, strings.ToLower(string(char))) {
return false
}
}
return true
}
// Anyway, returns all the networks
func GetNetworks() ([]Network, error) {
var networks []Network
collection, err := database.FetchRecords(database.NETWORKS_TABLE_NAME)
if err != nil {
return networks, err
}
for _, value := range collection {
var network Network
if err := json.Unmarshal([]byte(value), &network); err != nil {
return networks, err
}
// add network our array
networks = append(networks, network)
}
return networks, err
}
func (network *Network) IsNetworkDisplayNameUnique() (bool, error) {
isunique := true
records, err := GetNetworks()
if err != nil {
return false, err
}
for i := 0; i < len(records); i++ {
if network.NetID == records[i].DisplayName {
isunique = false
}
}
return isunique, nil
}
//Checks to see if any other networks have the same name (id)
func (network *Network) IsNetworkNameUnique() (bool, error) {
isunique := true
dbs, err := GetNetworks()
if err != nil {
return false, err
}
for i := 0; i < len(dbs); i++ {
if network.NetID == dbs[i].NetID {
isunique = false
}
}
return isunique, nil
}
func (network *Network) Validate() error {
v := validator.New()
_ = v.RegisterValidation("netid_valid", func(fl validator.FieldLevel) bool {
isFieldUnique, _ := network.IsNetworkNameUnique()
inCharSet := network.NetIDInNetworkCharSet()
return isFieldUnique && inCharSet
})
//
_ = v.RegisterValidation("displayname_valid", func(fl validator.FieldLevel) bool {
isFieldUnique, _ := network.IsNetworkDisplayNameUnique()
inCharSet := network.DisplayNameInNetworkCharSet()
return isFieldUnique && inCharSet
})
err := v.Struct(network)
return err
} }
//TODO: //TODO:
@@ -81,6 +191,15 @@ func (network *Network) SetNetworkLastModified() {
} }
func (network *Network) SetDefaults() { func (network *Network) SetDefaults() {
if network.DefaultUDPHolePunch == "" {
network.DefaultUDPHolePunch = "yes"
}
if network.IsLocal == "" {
network.IsLocal = "no"
}
if network.IsGRPCHub == "" {
network.IsGRPCHub = "no"
}
if network.DisplayName == "" { if network.DisplayName == "" {
network.DisplayName = network.NetID network.DisplayName = network.NetID
} }
@@ -97,31 +216,46 @@ func (network *Network) SetDefaults() {
if network.NodeLimit == 0 { if network.NodeLimit == 0 {
network.NodeLimit = 999999999 network.NodeLimit = 999999999
} }
if network.DefaultPostDown == "" { if network.DefaultSaveConfig == "" {
network.DefaultSaveConfig = "no"
}
if network.DefaultSaveConfig == nil {
defaultsave := true
network.DefaultSaveConfig = &defaultsave
} }
if network.DefaultKeepalive == 0 { if network.DefaultKeepalive == 0 {
network.DefaultKeepalive = 20 network.DefaultKeepalive = 20
} }
if network.DefaultPostUp == "" {
}
//Check-In Interval for Nodes, In Seconds //Check-In Interval for Nodes, In Seconds
if network.DefaultCheckInInterval == 0 { if network.DefaultCheckInInterval == 0 {
network.DefaultCheckInInterval = 30 network.DefaultCheckInInterval = 30
} }
if network.AllowManualSignUp == nil { if network.AllowManualSignUp == "" {
signup := false network.AllowManualSignUp = "no"
network.AllowManualSignUp = &signup
} }
if (network.IsDualStack != nil) && *network.IsDualStack { if network.IsDualStack == "" {
network.IsDualStack = "no"
}
if network.IsDualStack == "yes" {
network.IsIPv6 = "yes" network.IsIPv6 = "yes"
network.IsIPv4 = "yes" network.IsIPv4 = "yes"
} else if network.IsGRPCHub != "yes" { } else {
network.IsIPv6 = "no" network.IsIPv6 = "no"
network.IsIPv4 = "yes" network.IsIPv4 = "yes"
} }
} }
func (currentNetwork *Network) Update(newNetwork *Network) (bool, bool, error) {
if err := newNetwork.Validate(); err != nil {
return false, false, err
}
if newNetwork.NetID == currentNetwork.NetID {
hasrangeupdate := newNetwork.AddressRange != currentNetwork.AddressRange
localrangeupdate := newNetwork.LocalRange != currentNetwork.LocalRange
if data, err := json.Marshal(newNetwork); err != nil {
return false, false, err
} else {
newNetwork.SetNetworkLastModified()
err = database.Insert(newNetwork.NetID, string(data), database.NETWORKS_TABLE_NAME)
return hasrangeupdate, localrangeupdate, err
}
}
// copy values
return false, false, errors.New("failed to update network " + newNetwork.NetID + ", cannot change netid.")
}

View File

@@ -145,8 +145,8 @@ func (node *Node) SetDefaults() {
//TODO: This is dumb and doesn't work //TODO: This is dumb and doesn't work
//Need to change //Need to change
if node.SaveConfig == nil { if node.SaveConfig == nil {
if parentNetwork.DefaultSaveConfig != nil { if parentNetwork.DefaultSaveConfig != "" {
defaultsave := *parentNetwork.DefaultSaveConfig defaultsave := parentNetwork.DefaultSaveConfig == "yes"
node.SaveConfig = &defaultsave node.SaveConfig = &defaultsave
} }
} }

View File

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

View File

@@ -51,8 +51,7 @@ func CreateCommsNetwork() (bool, error) {
network.SetNodesLastModified() network.SetNodesLastModified()
network.SetNetworkLastModified() network.SetNetworkLastModified()
network.KeyUpdateTimeStamp = time.Now().Unix() network.KeyUpdateTimeStamp = time.Now().Unix()
priv := false network.IsLocal = "no"
network.IsLocal = &priv
network.KeyUpdateTimeStamp = time.Now().Unix() network.KeyUpdateTimeStamp = time.Now().Unix()
log.Println("Creating comms network...") log.Println("Creating comms network...")

View File

@@ -3,7 +3,7 @@
PUBKEY="DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=" PUBKEY="DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34="
IPADDR="69.173.21.202" IPADDR="69.173.21.202"
MACADDRESS="59:2a:9c:d4:e2:49" MACADDRESS="59:2a:9c:d4:e2:49"
ACCESSKEY="I6Pc8UFlszO1MWh3" ACCESSKEY="q5VHqUmamqsfgnpy"
PASSWORD="ppppppp" PASSWORD="ppppppp"
generate_post_json () generate_post_json ()
@@ -22,5 +22,5 @@ EOF
POST_JSON=$(generate_post_json) POST_JSON=$(generate_post_json)
curl --max-time 5.0 -d "$POST_JSON" -H 'Content-Type: application/json' -H "authorization: Bearer secretkey" localhost:8081/api/nodes/hello curl --max-time 5.0 -d "$POST_JSON" -H 'Content-Type: application/json' -H "authorization: Bearer secretkey" localhost:8081/api/nodes/my-net