|
@@ -1,36 +1,32 @@
|
|
|
package controller
|
|
|
|
|
|
import (
|
|
|
- "context"
|
|
|
"encoding/json"
|
|
|
"errors"
|
|
|
- "fmt"
|
|
|
"net/http"
|
|
|
"strings"
|
|
|
"time"
|
|
|
- "log"
|
|
|
+
|
|
|
"github.com/gorilla/mux"
|
|
|
+ "github.com/gravitl/netmaker/database"
|
|
|
"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"
|
|
|
+ "github.com/gravitl/netmaker/servercfg"
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
|
)
|
|
|
|
|
|
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}/{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(deleteNode))).Methods("DELETE")
|
|
|
- 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}/deletegateway", authorize(true, "master", http.HandlerFunc(deleteEgressGateway))).Methods("DELETE")
|
|
|
- r.HandleFunc("/api/nodes/{network}/{macaddress}/createingress", securityCheck(http.HandlerFunc(createIngressGateway))).Methods("POST")
|
|
|
- r.HandleFunc("/api/nodes/{network}/{macaddress}/deleteingress", securityCheck(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}/creategateway", authorize(true, "user", http.HandlerFunc(createEgressGateway))).Methods("POST")
|
|
|
+ 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}/deleteingress", securityCheck(false, http.HandlerFunc(deleteIngressGateway))).Methods("DELETE")
|
|
|
+ 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/adm/{network}/lastmodified", authorize(true, "network", http.HandlerFunc(getLastModified))).Methods("GET")
|
|
|
r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods("POST")
|
|
@@ -40,6 +36,8 @@ func nodeHandlers(r *mux.Router) {
|
|
|
//Node authenticates using its password and retrieves a JWT for authorization.
|
|
|
func authenticate(response http.ResponseWriter, request *http.Request) {
|
|
|
|
|
|
+ var params = mux.Vars(request)
|
|
|
+ networkname := params["network"]
|
|
|
//Auth request consists of Mac Address and Password (from node that is authorizing
|
|
|
//in case of Master, auth is ignored and mac is set to "mastermac"
|
|
|
var authRequest models.AuthParams
|
|
@@ -71,11 +69,21 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
|
|
|
} else {
|
|
|
|
|
|
//Search DB for node with Mac Address. Ignore pending nodes (they should not be able to authenticate with API untill approved).
|
|
|
- collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
|
|
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
- var err = collection.FindOne(ctx, bson.M{"macaddress": authRequest.MacAddress, "ispending": false}).Decode(&result)
|
|
|
-
|
|
|
- defer cancel()
|
|
|
+ collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
|
|
+ if err != nil {
|
|
|
+ errorResponse.Code = http.StatusBadRequest
|
|
|
+ errorResponse.Message = err.Error()
|
|
|
+ returnErrorResponse(response, request, errorResponse)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for _, value := range collection {
|
|
|
+ if err := json.Unmarshal([]byte(value), &result); err != nil {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if result.MacAddress == authRequest.MacAddress && result.IsPending != "yes" && result.Network == networkname {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
if err != nil {
|
|
|
errorResponse.Code = http.StatusBadRequest
|
|
@@ -138,7 +146,6 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
|
|
|
//TODO: Consider better RBAC implementations
|
|
|
func authorize(networkCheck bool, authNetwork string, next http.Handler) http.HandlerFunc {
|
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
|
-
|
|
|
var errorResponse = models.ErrorResponse{
|
|
|
Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
|
|
|
}
|
|
@@ -146,7 +153,6 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha
|
|
|
var params = mux.Vars(r)
|
|
|
|
|
|
networkexists, _ := functions.NetworkExists(params["network"])
|
|
|
-
|
|
|
//check that the request is for a valid network
|
|
|
//if (networkCheck && !networkexists) || err != nil {
|
|
|
if networkCheck && !networkexists {
|
|
@@ -155,9 +161,7 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha
|
|
|
}
|
|
|
returnErrorResponse(w, r, errorResponse)
|
|
|
return
|
|
|
-
|
|
|
} else {
|
|
|
-
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
|
//get the auth token
|
|
@@ -183,28 +187,24 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha
|
|
|
//A: the token is the master password
|
|
|
//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.
|
|
|
-
|
|
|
- var isAuthorized = false
|
|
|
+ var isAuthorized = false
|
|
|
var macaddress = ""
|
|
|
- _, isadmin, errN := functions.VerifyUserToken(authToken)
|
|
|
- if errN == nil && isadmin {
|
|
|
- macaddress = "mastermac"
|
|
|
- isAuthorized = true
|
|
|
- } else {
|
|
|
- mac, _, err := functions.VerifyToken(authToken)
|
|
|
- if err != nil {
|
|
|
- errorResponse = models.ErrorResponse{
|
|
|
- Code: http.StatusUnauthorized, Message: "W1R3: Error Verifying Auth Token.",
|
|
|
- }
|
|
|
- returnErrorResponse(w, r, errorResponse)
|
|
|
- return
|
|
|
+ username, networks, isadmin, errN := functions.VerifyUserToken(authToken)
|
|
|
+ isnetadmin := isadmin
|
|
|
+ if errN == nil && isadmin {
|
|
|
+ macaddress = "mastermac"
|
|
|
+ isAuthorized = true
|
|
|
+ r.Header.Set("ismasterkey", "yes")
|
|
|
+ }
|
|
|
+ if !isadmin && params["network"] != "" {
|
|
|
+ if functions.SliceContains(networks, params["network"]) {
|
|
|
+ isnetadmin = true
|
|
|
}
|
|
|
- macaddress = mac
|
|
|
}
|
|
|
//The mastermac (login with masterkey from config) can do everything!! May be dangerous.
|
|
|
if macaddress == "mastermac" {
|
|
|
isAuthorized = true
|
|
|
-
|
|
|
+ r.Header.Set("ismasterkey", "yes")
|
|
|
//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
|
|
|
} else {
|
|
@@ -212,21 +212,29 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha
|
|
|
case "all":
|
|
|
isAuthorized = true
|
|
|
case "nodes":
|
|
|
- isAuthorized = (macaddress != "")
|
|
|
+ isAuthorized = (macaddress != "") || isnetadmin
|
|
|
case "network":
|
|
|
- node, err := functions.GetNodeByMacAddress(params["network"], macaddress)
|
|
|
- if err != nil {
|
|
|
- errorResponse = models.ErrorResponse{
|
|
|
- Code: http.StatusUnauthorized, Message: "W1R3: Missing Auth Token.",
|
|
|
+ if isnetadmin {
|
|
|
+ isAuthorized = true
|
|
|
+ } else {
|
|
|
+ node, err := functions.GetNodeByMacAddress(params["network"], macaddress)
|
|
|
+ if err != nil {
|
|
|
+ errorResponse = models.ErrorResponse{
|
|
|
+ Code: http.StatusUnauthorized, Message: "W1R3: Missing Auth Token.",
|
|
|
+ }
|
|
|
+ returnErrorResponse(w, r, errorResponse)
|
|
|
+ return
|
|
|
}
|
|
|
- returnErrorResponse(w, r, errorResponse)
|
|
|
- return
|
|
|
+ isAuthorized = (node.Network == params["network"])
|
|
|
}
|
|
|
- isAuthorized = (node.Network == params["network"])
|
|
|
case "node":
|
|
|
- isAuthorized = (macaddress == params["macaddress"])
|
|
|
- case "master":
|
|
|
- isAuthorized = (macaddress == "mastermac")
|
|
|
+ if isnetadmin {
|
|
|
+ isAuthorized = true
|
|
|
+ } else {
|
|
|
+ isAuthorized = (macaddress == params["macaddress"])
|
|
|
+ }
|
|
|
+ case "user":
|
|
|
+ isAuthorized = true
|
|
|
default:
|
|
|
isAuthorized = false
|
|
|
}
|
|
@@ -239,6 +247,10 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha
|
|
|
return
|
|
|
} else {
|
|
|
//If authorized, this function passes along it's request and output to the appropriate route function.
|
|
|
+ if username == "" {
|
|
|
+ username = "(user not found)"
|
|
|
+ }
|
|
|
+ r.Header.Set("user", username)
|
|
|
next.ServeHTTP(w, r)
|
|
|
}
|
|
|
}
|
|
@@ -252,45 +264,38 @@ func getNetworkNodes(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
var nodes []models.Node
|
|
|
var params = mux.Vars(r)
|
|
|
- nodes, err := GetNetworkNodes(params["network"])
|
|
|
+ networkName := params["network"]
|
|
|
+ nodes, err := GetNetworkNodes(networkName)
|
|
|
if err != nil {
|
|
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
//Returns all the nodes in JSON format
|
|
|
+ functions.PrintUserLog(r.Header.Get("user"), "fetched nodes on network"+networkName, 2)
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
json.NewEncoder(w).Encode(nodes)
|
|
|
}
|
|
|
|
|
|
func GetNetworkNodes(network string) ([]models.Node, error) {
|
|
|
var nodes []models.Node
|
|
|
- collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
|
|
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
- filter := bson.M{"network": network}
|
|
|
- //Filtering out the ID field cuz Dillon doesn't like it. May want to filter out other fields in the future
|
|
|
- cur, err := collection.Find(ctx, filter, options.Find().SetProjection(bson.M{"_id": 0}))
|
|
|
- if err != nil {
|
|
|
- return []models.Node{}, err
|
|
|
- }
|
|
|
- defer cancel()
|
|
|
- for cur.Next(context.TODO()) {
|
|
|
- //Using a different model for the Node (other than regular node).
|
|
|
- //Either we should do this for ALL structs (so Networks and Keys)
|
|
|
- //OR we should just use the original struct
|
|
|
- //My preference is to make some new return structs
|
|
|
- //TODO: Think about this. Not an immediate concern. Just need to get some consistency eventually
|
|
|
+ collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
|
|
+ if err != nil {
|
|
|
+ if database.IsEmptyRecord(err) {
|
|
|
+ return []models.Node{}, nil
|
|
|
+ }
|
|
|
+ return nodes, err
|
|
|
+ }
|
|
|
+ for _, value := range collection {
|
|
|
+
|
|
|
var node models.Node
|
|
|
- err := cur.Decode(&node)
|
|
|
+ err := json.Unmarshal([]byte(value), &node)
|
|
|
if err != nil {
|
|
|
- return []models.Node{}, err
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if node.Network == network {
|
|
|
+ nodes = append(nodes, node)
|
|
|
}
|
|
|
- // add item our array of nodes
|
|
|
- nodes = append(nodes, node)
|
|
|
- }
|
|
|
- //TODO: Another fatal error we should take care of.
|
|
|
- if err := cur.Err(); err != nil {
|
|
|
- return []models.Node{}, err
|
|
|
}
|
|
|
return nodes, nil
|
|
|
}
|
|
@@ -299,70 +304,42 @@ 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
|
|
|
func getAllNodes(w http.ResponseWriter, r *http.Request) {
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
- nodes, err := functions.GetAllNodes()
|
|
|
- if err != nil {
|
|
|
+ user, err := functions.GetUser(r.Header.Get("user"))
|
|
|
+ if err != nil && r.Header.Get("ismasterkey") != "yes" {
|
|
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
return
|
|
|
}
|
|
|
+ var nodes []models.Node
|
|
|
+ if user.IsAdmin || r.Header.Get("ismasterkey") == "yes" {
|
|
|
+ nodes, err = models.GetAllNodes()
|
|
|
+ if err != nil {
|
|
|
+ returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ nodes, err = getUsersNodes(user)
|
|
|
+ if err != nil {
|
|
|
+ returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
//Return all the nodes in JSON format
|
|
|
+ functions.PrintUserLog(r.Header.Get("user"), "fetched nodes", 2)
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
json.NewEncoder(w).Encode(nodes)
|
|
|
}
|
|
|
|
|
|
-//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
|
|
|
-//TODO: Implement the necessary stuff, including the below
|
|
|
-//Check the last modified of the network
|
|
|
-//Check the last modified of the nodes
|
|
|
-//Write functions for responding to these two thingies
|
|
|
-func checkIn(w http.ResponseWriter, r *http.Request) {
|
|
|
-
|
|
|
- //TODO: Current thoughts:
|
|
|
- //Dont bother with a networklastmodified
|
|
|
- //Instead, implement a "configupdate" boolean on nodes
|
|
|
- //when there is a network update that requrires a config update, then the node will pull its new config
|
|
|
-
|
|
|
- // set header.
|
|
|
- w.Header().Set("Content-Type", "application/json")
|
|
|
-
|
|
|
- var params = mux.Vars(r)
|
|
|
- node, err := CheckIn(params["network"], params["macaddress"])
|
|
|
- if err != nil {
|
|
|
- returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
- return
|
|
|
- }
|
|
|
- w.WriteHeader(http.StatusOK)
|
|
|
- json.NewEncoder(w).Encode(node)
|
|
|
-}
|
|
|
-func CheckIn(network, macaddress string) (models.Node, error) {
|
|
|
- var node models.Node
|
|
|
-
|
|
|
- //Retrieves node with DB Call which is inefficient. Let's just get the time and set it.
|
|
|
- //node = functions.GetNodeByMacAddress(params["network"], params["macaddress"])
|
|
|
- collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
|
|
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
- filter := bson.M{"macaddress": macaddress, "network": network}
|
|
|
- //old code was inefficient, this is all we need.
|
|
|
- time := time.Now().Unix()
|
|
|
- //node.SetLastCheckIn()
|
|
|
- // prepare update model with new time
|
|
|
- update := bson.D{
|
|
|
- {"$set", bson.D{
|
|
|
- {"lastcheckin", time},
|
|
|
- }},
|
|
|
- }
|
|
|
- err := collection.FindOneAndUpdate(ctx, filter, update).Decode(&node)
|
|
|
- defer cancel()
|
|
|
- if err != nil {
|
|
|
- return models.Node{}, err
|
|
|
- }
|
|
|
- //TODO: check node last modified vs network last modified
|
|
|
- //Get Updated node to return
|
|
|
- node, err = GetNode(macaddress, network)
|
|
|
- if err != nil {
|
|
|
- return models.Node{}, err
|
|
|
+func getUsersNodes(user models.User) ([]models.Node, error) {
|
|
|
+ var nodes []models.Node
|
|
|
+ var err error
|
|
|
+ for _, networkName := range user.Networks {
|
|
|
+ tmpNodes, err := GetNetworkNodes(networkName)
|
|
|
+ if err != nil {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ nodes = append(nodes, tmpNodes...)
|
|
|
}
|
|
|
- return node, nil
|
|
|
+ return nodes, err
|
|
|
}
|
|
|
|
|
|
//Get an individual node. Nothin fancy here folks.
|
|
@@ -377,6 +354,7 @@ func getNode(w http.ResponseWriter, r *http.Request) {
|
|
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
return
|
|
|
}
|
|
|
+ functions.PrintUserLog(r.Header.Get("user"), "fetched node "+params["macaddress"], 2)
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
json.NewEncoder(w).Encode(node)
|
|
|
}
|
|
@@ -390,32 +368,16 @@ func getLastModified(w http.ResponseWriter, r *http.Request) {
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
|
var params = mux.Vars(r)
|
|
|
- network, err := GetLastModified(params["network"])
|
|
|
+ network, err := GetNetwork(params["network"])
|
|
|
if err != nil {
|
|
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
return
|
|
|
}
|
|
|
+ functions.PrintUserLog(r.Header.Get("user"), "called last modified", 2)
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
json.NewEncoder(w).Encode(network.NodesLastModified)
|
|
|
}
|
|
|
|
|
|
-func GetLastModified(network string) (models.Network, error) {
|
|
|
- var net models.Network
|
|
|
- collection := mongoconn.Client.Database("netmaker").Collection("networks")
|
|
|
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
- filter := bson.M{"netid": network}
|
|
|
- err := collection.FindOne(ctx, filter).Decode(&net)
|
|
|
- defer cancel()
|
|
|
- if err != nil {
|
|
|
- fmt.Println(err)
|
|
|
- return models.Network{}, err
|
|
|
- }
|
|
|
- return net, nil
|
|
|
-}
|
|
|
-
|
|
|
-//This one's a doozy
|
|
|
-//To create a node
|
|
|
-//Must have valid key and be unique
|
|
|
func createNode(w http.ResponseWriter, r *http.Request) {
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
@@ -424,12 +386,7 @@ func createNode(w http.ResponseWriter, r *http.Request) {
|
|
|
var errorResponse = models.ErrorResponse{
|
|
|
Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
|
|
|
}
|
|
|
-
|
|
|
networkName := params["network"]
|
|
|
-
|
|
|
- //Check if network exists first
|
|
|
- //TODO: This is inefficient. Let's find a better way.
|
|
|
- //Just a few rows down we grab the network anyway
|
|
|
networkexists, err := functions.NetworkExists(networkName)
|
|
|
|
|
|
if err != nil {
|
|
@@ -467,8 +424,8 @@ func createNode(w http.ResponseWriter, r *http.Request) {
|
|
|
if !validKey {
|
|
|
//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.
|
|
|
- if *network.AllowManualSignUp {
|
|
|
- node.IsPending = true
|
|
|
+ if network.AllowManualSignUp == "yes" {
|
|
|
+ node.IsPending = "yes"
|
|
|
} else {
|
|
|
errorResponse = models.ErrorResponse{
|
|
|
Code: http.StatusUnauthorized, Message: "W1R3: Key invalid, or none provided.",
|
|
@@ -478,17 +435,12 @@ func createNode(w http.ResponseWriter, r *http.Request) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- err = ValidateNodeCreate(networkName, node)
|
|
|
- if err != nil {
|
|
|
- returnErrorResponse(w, r, formatError(err, "badrequest"))
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
node, err = CreateNode(node, networkName)
|
|
|
if err != nil {
|
|
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
return
|
|
|
}
|
|
|
+ functions.PrintUserLog(r.Header.Get("user"), "created new node "+node.Name+" on network "+node.Network, 1)
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
json.NewEncoder(w).Encode(node)
|
|
|
}
|
|
@@ -503,7 +455,7 @@ func uncordonNode(w http.ResponseWriter, r *http.Request) {
|
|
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
return
|
|
|
}
|
|
|
- fmt.Println("Node " + node.Name + " uncordoned.")
|
|
|
+ functions.PrintUserLog(r.Header.Get("user"), "uncordoned node "+node.Name, 1)
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
json.NewEncoder(w).Encode("SUCCESS")
|
|
|
}
|
|
@@ -513,24 +465,20 @@ func UncordonNode(network, macaddress string) (models.Node, error) {
|
|
|
if err != nil {
|
|
|
return models.Node{}, err
|
|
|
}
|
|
|
- collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
|
|
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
- // Create filter
|
|
|
- filter := bson.M{"macaddress": macaddress, "network": network}
|
|
|
node.SetLastModified()
|
|
|
- fmt.Println("Uncordoning node " + node.Name)
|
|
|
- // prepare update model.
|
|
|
- update := bson.D{
|
|
|
- {"$set", bson.D{
|
|
|
- {"ispending", false},
|
|
|
- }},
|
|
|
+ node.IsPending = "no"
|
|
|
+ node.PullChanges = "yes"
|
|
|
+ data, err := json.Marshal(&node)
|
|
|
+ if err != nil {
|
|
|
+ return node, err
|
|
|
}
|
|
|
- err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&node)
|
|
|
- defer cancel()
|
|
|
+ key, err := functions.GetRecordKey(node.MacAddress, node.Network)
|
|
|
if err != nil {
|
|
|
- return models.Node{}, err
|
|
|
+ return node, err
|
|
|
}
|
|
|
- return node, nil
|
|
|
+
|
|
|
+ err = database.Insert(key, string(data), database.NODES_TABLE_NAME)
|
|
|
+ return node, err
|
|
|
}
|
|
|
|
|
|
func createEgressGateway(w http.ResponseWriter, r *http.Request) {
|
|
@@ -549,6 +497,7 @@ func createEgressGateway(w http.ResponseWriter, r *http.Request) {
|
|
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
return
|
|
|
}
|
|
|
+ functions.PrintUserLog(r.Header.Get("user"), "created egress gateway on node "+gateway.NodeID+" on network "+gateway.NetID, 1)
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
json.NewEncoder(w).Encode(node)
|
|
|
}
|
|
@@ -562,59 +511,42 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro
|
|
|
if err != nil {
|
|
|
return models.Node{}, err
|
|
|
}
|
|
|
- var nodechange models.Node
|
|
|
- nodechange.IsEgressGateway = true
|
|
|
- nodechange.EgressGatewayRange = gateway.RangeString
|
|
|
- nodechange.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -A POSTROUTING -o " + gateway.Interface + " -j MASQUERADE"
|
|
|
- nodechange.PostDown = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -D POSTROUTING -o " + gateway.Interface + " -j MASQUERADE"
|
|
|
+ node.IsEgressGateway = "yes"
|
|
|
+ node.EgressGatewayRanges = gateway.Ranges
|
|
|
+ postUpCmd := "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -A POSTROUTING -o " + gateway.Interface + " -j MASQUERADE"
|
|
|
+ postDownCmd := "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -D POSTROUTING -o " + gateway.Interface + " -j MASQUERADE"
|
|
|
if gateway.PostUp != "" {
|
|
|
- nodechange.PostUp = gateway.PostUp
|
|
|
+ postUpCmd = gateway.PostUp
|
|
|
}
|
|
|
if gateway.PostDown != "" {
|
|
|
- nodechange.PostDown = gateway.PostDown
|
|
|
+ postDownCmd = gateway.PostDown
|
|
|
}
|
|
|
if node.PostUp != "" {
|
|
|
- if !strings.Contains(node.PostUp, nodechange.PostUp) {
|
|
|
- nodechange.PostUp = node.PostUp + "; " + nodechange.PostUp
|
|
|
- } else {
|
|
|
- nodechange.PostUp = node.PostUp
|
|
|
+ if !strings.Contains(node.PostUp, postUpCmd) {
|
|
|
+ postUpCmd = node.PostUp + "; " + postUpCmd
|
|
|
}
|
|
|
}
|
|
|
- if node.PostDown != "" {
|
|
|
- if !strings.Contains(node.PostDown, nodechange.PostDown) {
|
|
|
- nodechange.PostDown = node.PostDown + "; " + nodechange.PostDown
|
|
|
- } else {
|
|
|
- nodechange.PostDown = node.PostDown
|
|
|
- }
|
|
|
- }
|
|
|
- collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
|
|
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
- // Create filter
|
|
|
- filter := bson.M{"macaddress": gateway.NodeID, "network": gateway.NetID}
|
|
|
- nodechange.SetLastModified()
|
|
|
- // prepare update model.
|
|
|
- update := bson.D{
|
|
|
- {"$set", bson.D{
|
|
|
- {"postup", nodechange.PostUp},
|
|
|
- {"postdown", nodechange.PostDown},
|
|
|
- {"isegressgateway", nodechange.IsEgressGateway},
|
|
|
- {"egressgatewayrange", nodechange.EgressGatewayRange},
|
|
|
- {"lastmodified", nodechange.LastModified},
|
|
|
- }},
|
|
|
- }
|
|
|
- var nodeupdate models.Node
|
|
|
- err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&nodeupdate)
|
|
|
- defer cancel()
|
|
|
+ if node.PostDown != "" {
|
|
|
+ if !strings.Contains(node.PostDown, postDownCmd) {
|
|
|
+ postDownCmd = node.PostDown + "; " + postDownCmd
|
|
|
+ }
|
|
|
+ }
|
|
|
+ key, err := functions.GetRecordKey(gateway.NodeID, gateway.NetID)
|
|
|
if err != nil {
|
|
|
- return models.Node{}, err
|
|
|
+ return node, err
|
|
|
}
|
|
|
- err = SetNetworkNodesLastModified(gateway.NetID)
|
|
|
+ node.PostUp = postUpCmd
|
|
|
+ node.PostDown = postDownCmd
|
|
|
+ node.SetLastModified()
|
|
|
+ node.PullChanges = "yes"
|
|
|
+ nodeData, err := json.Marshal(&node)
|
|
|
if err != nil {
|
|
|
+ return node, err
|
|
|
+ }
|
|
|
+ if err = database.Insert(key, string(nodeData), database.NODES_TABLE_NAME); err != nil {
|
|
|
return models.Node{}, err
|
|
|
}
|
|
|
- //Get updated values to return
|
|
|
- node, err = functions.GetNodeByMacAddress(gateway.NetID, gateway.NodeID)
|
|
|
- if err != nil {
|
|
|
+ if err = functions.NetworkNodesUpdatePullChanges(node.Network); err != nil {
|
|
|
return models.Node{}, err
|
|
|
}
|
|
|
return node, nil
|
|
@@ -622,10 +554,10 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro
|
|
|
|
|
|
func ValidateEgressGateway(gateway models.EgressGatewayRequest) error {
|
|
|
var err error
|
|
|
- isIp := functions.IsIpCIDR(gateway.RangeString)
|
|
|
- empty := gateway.RangeString == ""
|
|
|
- if empty || !isIp {
|
|
|
- err = errors.New("IP Range Not Valid")
|
|
|
+ //isIp := functions.IsIpCIDR(gateway.RangeString)
|
|
|
+ empty := len(gateway.Ranges) == 0
|
|
|
+ if empty {
|
|
|
+ err = errors.New("IP Ranges Cannot Be Empty")
|
|
|
}
|
|
|
empty = gateway.Interface == ""
|
|
|
if empty {
|
|
@@ -637,69 +569,60 @@ func ValidateEgressGateway(gateway models.EgressGatewayRequest) error {
|
|
|
func deleteEgressGateway(w http.ResponseWriter, r *http.Request) {
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
var params = mux.Vars(r)
|
|
|
- node, err := DeleteEgressGateway(params["network"], params["macaddress"])
|
|
|
+ nodeMac := params["macaddress"]
|
|
|
+ netid := params["network"]
|
|
|
+ node, err := DeleteEgressGateway(netid, nodeMac)
|
|
|
if err != nil {
|
|
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
return
|
|
|
}
|
|
|
+ functions.PrintUserLog(r.Header.Get("user"), "deleted egress gateway "+nodeMac+" on network "+netid, 1)
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
json.NewEncoder(w).Encode(node)
|
|
|
}
|
|
|
|
|
|
func DeleteEgressGateway(network, macaddress string) (models.Node, error) {
|
|
|
|
|
|
- var nodeupdate models.Node
|
|
|
- var nodechange models.Node
|
|
|
node, err := functions.GetNodeByMacAddress(network, macaddress)
|
|
|
if err != nil {
|
|
|
return models.Node{}, err
|
|
|
}
|
|
|
|
|
|
- nodechange.IsEgressGateway = false
|
|
|
- nodechange.EgressGatewayRange = ""
|
|
|
- nodechange.PostUp = ""
|
|
|
- nodechange.PostDown = ""
|
|
|
-
|
|
|
- collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
|
|
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
- // Create filter
|
|
|
- filter := bson.M{"macaddress": macaddress, "network": network}
|
|
|
- nodechange.SetLastModified()
|
|
|
- // prepare update model.
|
|
|
- update := bson.D{
|
|
|
- {"$set", bson.D{
|
|
|
- {"postup", nodechange.PostUp},
|
|
|
- {"postdown", nodechange.PostDown},
|
|
|
- {"isegressgateway", nodechange.IsEgressGateway},
|
|
|
- {"egressgatewayrange", nodechange.EgressGatewayRange},
|
|
|
- {"lastmodified", nodechange.LastModified},
|
|
|
- }},
|
|
|
- }
|
|
|
- err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&nodeupdate)
|
|
|
- defer cancel()
|
|
|
+ node.IsEgressGateway = "no"
|
|
|
+ node.EgressGatewayRanges = []string{}
|
|
|
+ node.PostUp = ""
|
|
|
+ node.PostDown = ""
|
|
|
+ node.SetLastModified()
|
|
|
+ node.PullChanges = "yes"
|
|
|
+ key, err := functions.GetRecordKey(node.MacAddress, node.Network)
|
|
|
if err != nil {
|
|
|
return models.Node{}, err
|
|
|
}
|
|
|
- err = SetNetworkNodesLastModified(network)
|
|
|
+ data, err := json.Marshal(&node)
|
|
|
if err != nil {
|
|
|
return models.Node{}, err
|
|
|
}
|
|
|
- //Get updated values to return
|
|
|
- node, err = functions.GetNodeByMacAddress(network, macaddress)
|
|
|
- if err != nil {
|
|
|
+ if err = database.Insert(key, string(data), database.NODES_TABLE_NAME); err != nil {
|
|
|
+ return models.Node{}, err
|
|
|
+ }
|
|
|
+ if err = functions.NetworkNodesUpdatePullChanges(network); err != nil {
|
|
|
return models.Node{}, err
|
|
|
}
|
|
|
return node, nil
|
|
|
}
|
|
|
+
|
|
|
// == INGRESS ==
|
|
|
func createIngressGateway(w http.ResponseWriter, r *http.Request) {
|
|
|
var params = mux.Vars(r)
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
- node, err := CreateIngressGateway(params["network"], params["macaddress"])
|
|
|
+ nodeMac := params["macaddress"]
|
|
|
+ netid := params["network"]
|
|
|
+ node, err := CreateIngressGateway(netid, nodeMac)
|
|
|
if err != nil {
|
|
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
return
|
|
|
}
|
|
|
+ functions.PrintUserLog(r.Header.Get("user"), "created ingress gateway on node "+nodeMac+" on network "+netid, 1)
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
json.NewEncoder(w).Encode(node)
|
|
|
}
|
|
@@ -707,115 +630,98 @@ func createIngressGateway(w http.ResponseWriter, r *http.Request) {
|
|
|
func CreateIngressGateway(netid string, macaddress string) (models.Node, error) {
|
|
|
|
|
|
node, err := functions.GetNodeByMacAddress(netid, macaddress)
|
|
|
- if err != nil {
|
|
|
- return models.Node{}, err
|
|
|
- }
|
|
|
-
|
|
|
- network, err := functions.GetParentNetwork(netid)
|
|
|
- if err != nil {
|
|
|
- log.Println("Could not find network.")
|
|
|
- return models.Node{}, err
|
|
|
- }
|
|
|
- var nodechange models.Node
|
|
|
- nodechange.IngressGatewayRange = network.AddressRange
|
|
|
- nodechange.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE"
|
|
|
- nodechange.PostDown = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE"
|
|
|
- if node.PostUp != "" {
|
|
|
- if !strings.Contains(node.PostUp, nodechange.PostUp) {
|
|
|
- nodechange.PostUp = node.PostUp + "; " + nodechange.PostUp
|
|
|
- } else {
|
|
|
- nodechange.PostUp = node.PostUp
|
|
|
- }
|
|
|
- }
|
|
|
- if node.PostDown != "" {
|
|
|
- if !strings.Contains(node.PostDown, nodechange.PostDown) {
|
|
|
- nodechange.PostDown = node.PostDown + "; " + nodechange.PostDown
|
|
|
- } else {
|
|
|
- nodechange.PostDown = node.PostDown
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
|
|
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
- // Create filter
|
|
|
- filter := bson.M{"macaddress": macaddress, "network": netid}
|
|
|
- node.SetLastModified()
|
|
|
- // prepare update model.
|
|
|
- update := bson.D{
|
|
|
- {"$set", bson.D{
|
|
|
- {"postup", nodechange.PostUp},
|
|
|
- {"postdown", nodechange.PostDown},
|
|
|
- {"isingressgateway", true},
|
|
|
- {"ingressgatewayrange", nodechange.IngressGatewayRange},
|
|
|
- {"lastmodified", node.LastModified},
|
|
|
- }},
|
|
|
- }
|
|
|
- var nodeupdate models.Node
|
|
|
- err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&nodeupdate)
|
|
|
- defer cancel()
|
|
|
- if err != nil {
|
|
|
- log.Println("error updating node to gateway")
|
|
|
- return models.Node{}, err
|
|
|
- }
|
|
|
- err = SetNetworkNodesLastModified(netid)
|
|
|
- if err != nil {
|
|
|
- return node, err
|
|
|
- }
|
|
|
- //Get updated values to return
|
|
|
- node, err = functions.GetNodeByMacAddress(netid, macaddress)
|
|
|
- if err != nil {
|
|
|
- log.Println("error finding node after update")
|
|
|
- return node, err
|
|
|
- }
|
|
|
- return node, nil
|
|
|
+ if err != nil {
|
|
|
+ return models.Node{}, err
|
|
|
+ }
|
|
|
+
|
|
|
+ network, err := functions.GetParentNetwork(netid)
|
|
|
+ if err != nil {
|
|
|
+ return models.Node{}, err
|
|
|
+ }
|
|
|
+ node.IsIngressGateway = "yes"
|
|
|
+ node.IngressGatewayRange = network.AddressRange
|
|
|
+ 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"
|
|
|
+ if node.PostUp != "" {
|
|
|
+ if !strings.Contains(node.PostUp, postUpCmd) {
|
|
|
+ postUpCmd = node.PostUp + "; " + postUpCmd
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if node.PostDown != "" {
|
|
|
+ if !strings.Contains(node.PostDown, postDownCmd) {
|
|
|
+ postDownCmd = node.PostDown + "; " + postDownCmd
|
|
|
+ }
|
|
|
+ }
|
|
|
+ node.SetLastModified()
|
|
|
+ node.PostUp = postUpCmd
|
|
|
+ node.PostDown = postDownCmd
|
|
|
+ node.PullChanges = "yes"
|
|
|
+ node.UDPHolePunch = "no"
|
|
|
+ key, err := functions.GetRecordKey(node.MacAddress, node.Network)
|
|
|
+ if err != nil {
|
|
|
+ return models.Node{}, err
|
|
|
+ }
|
|
|
+ data, err := json.Marshal(&node)
|
|
|
+ if err != nil {
|
|
|
+ return models.Node{}, err
|
|
|
+ }
|
|
|
+ err = database.Insert(key, string(data), database.NODES_TABLE_NAME)
|
|
|
+ if err != nil {
|
|
|
+ return models.Node{}, err
|
|
|
+ }
|
|
|
+ err = SetNetworkNodesLastModified(netid)
|
|
|
+ return node, err
|
|
|
}
|
|
|
|
|
|
func deleteIngressGateway(w http.ResponseWriter, r *http.Request) {
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
var params = mux.Vars(r)
|
|
|
- node, err := DeleteIngressGateway(params["network"], params["macaddress"])
|
|
|
+ nodeMac := params["macaddress"]
|
|
|
+ node, err := DeleteIngressGateway(params["network"], nodeMac)
|
|
|
if err != nil {
|
|
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
return
|
|
|
}
|
|
|
+ functions.PrintUserLog(r.Header.Get("user"), "deleted ingress gateway"+nodeMac, 1)
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
json.NewEncoder(w).Encode(node)
|
|
|
}
|
|
|
|
|
|
-func DeleteIngressGateway(network, macaddress string) (models.Node, error) {
|
|
|
+func DeleteIngressGateway(networkName string, macaddress string) (models.Node, error) {
|
|
|
|
|
|
- var nodeupdate models.Node
|
|
|
- node, err := functions.GetNodeByMacAddress(network, macaddress)
|
|
|
+ node, err := functions.GetNodeByMacAddress(networkName, macaddress)
|
|
|
if err != nil {
|
|
|
return models.Node{}, err
|
|
|
}
|
|
|
-
|
|
|
- collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
|
|
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
- // Create filter
|
|
|
- filter := bson.M{"macaddress": macaddress, "network": network}
|
|
|
- // prepare update model.
|
|
|
- update := bson.D{
|
|
|
- {"$set", bson.D{
|
|
|
- {"lastmodified", time.Now().Unix()},
|
|
|
- {"isingressgateway", false},
|
|
|
- }},
|
|
|
+ network, err := functions.GetParentNetwork(networkName)
|
|
|
+ if err != nil {
|
|
|
+ return models.Node{}, err
|
|
|
+ }
|
|
|
+ // delete ext clients belonging to ingress gateway
|
|
|
+ if err = DeleteGatewayExtClients(macaddress, networkName); err != nil {
|
|
|
+ return models.Node{}, err
|
|
|
}
|
|
|
- err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&nodeupdate)
|
|
|
- defer cancel()
|
|
|
+
|
|
|
+ node.UDPHolePunch = network.DefaultUDPHolePunch
|
|
|
+ node.LastModified = time.Now().Unix()
|
|
|
+ node.IsIngressGateway = "no"
|
|
|
+ node.IngressGatewayRange = ""
|
|
|
+ node.PullChanges = "yes"
|
|
|
+
|
|
|
+ key, err := functions.GetRecordKey(node.MacAddress, node.Network)
|
|
|
if err != nil {
|
|
|
return models.Node{}, err
|
|
|
}
|
|
|
- err = SetNetworkNodesLastModified(network)
|
|
|
+ data, err := json.Marshal(&node)
|
|
|
if err != nil {
|
|
|
return models.Node{}, err
|
|
|
}
|
|
|
- //Get updated values to return
|
|
|
- node, err = functions.GetNodeByMacAddress(network, macaddress)
|
|
|
+ err = database.Insert(key, string(data), database.NODES_TABLE_NAME)
|
|
|
if err != nil {
|
|
|
return models.Node{}, err
|
|
|
}
|
|
|
- return node, nil
|
|
|
+ err = SetNetworkNodesLastModified(networkName)
|
|
|
+ return node, err
|
|
|
}
|
|
|
|
|
|
func updateNode(w http.ResponseWriter, r *http.Request) {
|
|
@@ -823,11 +729,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
var params = mux.Vars(r)
|
|
|
|
|
|
- //Get id from parameters
|
|
|
- //id, _ := primitive.ObjectIDFromHex(params["id"])
|
|
|
-
|
|
|
var node models.Node
|
|
|
-
|
|
|
//start here
|
|
|
node, err := functions.GetNodeByMacAddress(params["network"], params["macaddress"])
|
|
|
if err != nil {
|
|
@@ -835,29 +737,30 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- var nodechange models.NodeUpdate
|
|
|
-
|
|
|
+ var newNode models.Node
|
|
|
// we decode our body request params
|
|
|
- _ = json.NewDecoder(r.Body).Decode(&nodechange)
|
|
|
- if nodechange.Network == "" {
|
|
|
- nodechange.Network = node.Network
|
|
|
- }
|
|
|
- if nodechange.MacAddress == "" {
|
|
|
- nodechange.MacAddress = node.MacAddress
|
|
|
- }
|
|
|
- err = ValidateNodeUpdate(params["network"], nodechange)
|
|
|
+ err = json.NewDecoder(r.Body).Decode(&newNode)
|
|
|
if err != nil {
|
|
|
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
|
|
return
|
|
|
}
|
|
|
+ newNode.PullChanges = "yes"
|
|
|
+ err = node.Update(&newNode)
|
|
|
+ if err != nil {
|
|
|
+ returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
- node, err = UpdateNode(nodechange, node)
|
|
|
+ if servercfg.IsDNSMode() {
|
|
|
+ err = SetDNS()
|
|
|
+ }
|
|
|
if err != nil {
|
|
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
return
|
|
|
}
|
|
|
+ functions.PrintUserLog(r.Header.Get("user"), "updated node "+node.MacAddress+" on network "+node.Network, 1)
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
- json.NewEncoder(w).Encode(node)
|
|
|
+ json.NewEncoder(w).Encode(newNode)
|
|
|
}
|
|
|
|
|
|
//Delete a node
|
|
@@ -869,15 +772,12 @@ func deleteNode(w http.ResponseWriter, r *http.Request) {
|
|
|
// get params
|
|
|
var params = mux.Vars(r)
|
|
|
|
|
|
- success, err := DeleteNode(params["macaddress"], params["network"])
|
|
|
+ err := DeleteNode(params["macaddress"]+"###"+params["network"], false)
|
|
|
|
|
|
if err != nil {
|
|
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
return
|
|
|
- } else if !success {
|
|
|
- err = errors.New("Could not delete node " + params["macaddress"])
|
|
|
- returnErrorResponse(w, r, formatError(err, "internal"))
|
|
|
- return
|
|
|
}
|
|
|
+ functions.PrintUserLog(r.Header.Get("user"), "Deleted node "+params["macaddress"]+" from network "+params["network"], 1)
|
|
|
returnSuccessResponse(w, r, params["macaddress"]+" deleted.")
|
|
|
}
|