Files
netmaker/controllers/externalHttpController.go.backup

234 lines
7.2 KiB
Plaintext

package controller
import (
"context"
"encoding/json"
"errors"
// "fmt"
"net/http"
"time"
"github.com/gorilla/mux"
"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/skip2/go-qrcode"
)
func externalHandlers(r *mux.Router) {
r.HandleFunc("/api/externals", securityCheck(http.HandlerFunc(getAllExternals))).Methods("GET")
r.HandleFunc("/api/externals/{network}", securityCheck(http.HandlerFunc(getNetworkExternals))).Methods("GET")
r.HandleFunc("/api/externals/{network}/{clientid}", securityCheck(http.HandlerFunc(getExternal))).Methods("GET")
r.HandleFunc("/api/externals/{network}/{clientid}/qr", securityCheck(http.HandlerFunc(getExternal))).Methods("GET")
r.HandleFunc("/api/externals/{network}/{ingressgateway}", securityCheck(http.HandlerFunc(getExternal))).Methods("GET")
r.HandleFunc("/api/externals/{network}/{clientid}", securityCheck(http.HandlerFunc(updateExternal))).Methods("PUT")
r.HandleFunc("/api/externals/{network}/{clientid}", securityCheck(http.HandlerFunc(deleteExternal))).Methods("DELETE")
r.HandleFunc("/api/externals/{network}", securityCheck(http.HandlerFunc(createExternal))).Methods("POST")
}
//Gets all nodes associated with network, including pending nodes
func getNetworkExternals(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var nodes []models.External
var params = mux.Vars(r)
nodes, err := GetNetworkExternals(params["network"])
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
//Returns all the nodes in JSON format
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(nodes)
}
func GetNetworkExternals(network string) ([]models.External, error) {
var nodes []models.External
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.External{}, err
}
defer cancel()
for cur.Next(context.TODO()) {
//Using a different model for the ReturnExternal (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
var node models.External
err := cur.Decode(&node)
if err != nil {
return []models.External{}, err
}
// 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.External{}, err
}
return nodes, nil
}
//A separate function to get all nodes, not just nodes for a particular network.
//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 getAllExternals(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
nodes, err := functions.GetAllExternals()
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
//Return all the nodes in JSON format
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(nodes)
}
//Get an individual node. Nothin fancy here folks.
func getExternal(w http.ResponseWriter, r *http.Request) {
// set header.
w.Header().Set("Content-Type", "application/json")
var params = mux.Vars(r)
var node models.Node
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"macaddress": params["macaddress"], "network": params["network"]}
err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&node)
defer cancel()
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(node)
}
//This one's a doozy
//To create a node
//Must have valid key and be unique
func createExternal(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var params = mux.Vars(r)
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 {
returnErrorResponse(w, r, formatError(err, "internal"))
return
} else if !networkexists {
errorResponse = models.ErrorResponse{
Code: http.StatusNotFound, Message: "W1R3: Network does not exist! ",
}
returnErrorResponse(w, r, errorResponse)
return
}
var external models.External
//get node from body of request
err = json.NewDecoder(r.Body).Decode(&external)
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
err = ValidateExternalCreate(external)
if err != nil {
returnErrorResponse(w, r, formatError(err, "badrequest"))
return
}
node, err = CreateExternal(node, networkName)
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(node)
}
func updateExternal(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var params = mux.Vars(r)
//Get id from parameters
//id, _ := primitive.ObjectIDFromHex(params["id"])
var node models.External
//start here
node, err := functions.GetExternalByMacAddress(params["network"], params["macaddress"])
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
var nodechange models.ExternalUpdate
// 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 = ValidateExternalUpdate(params["network"], nodechange)
if err != nil {
returnErrorResponse(w, r, formatError(err, "badrequest"))
return
}
node, err = UpdateExternal(nodechange, node)
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(node)
}
//Delete a node
//Pretty straightforward
func deleteExternal(w http.ResponseWriter, r *http.Request) {
// Set header
w.Header().Set("Content-Type", "application/json")
// get params
var params = mux.Vars(r)
success, err := DeleteExternal(params["macaddress"], params["network"])
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
}
returnSuccessResponse(w, r, params["macaddress"]+" deleted.")
}