mirror of
https://github.com/gravitl/netmaker.git
synced 2025-10-05 08:47:35 +08:00
changed all error responses
This commit is contained in:
BIN
controllers/.nodeHttpController.go.swp
Normal file
BIN
controllers/.nodeHttpController.go.swp
Normal file
Binary file not shown.
@@ -3,6 +3,7 @@ package controller
|
|||||||
import (
|
import (
|
||||||
"gopkg.in/go-playground/validator.v9"
|
"gopkg.in/go-playground/validator.v9"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
|
"errors"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"github.com/gravitl/netmaker/functions"
|
"github.com/gravitl/netmaker/functions"
|
||||||
"github.com/gravitl/netmaker/mongoconn"
|
"github.com/gravitl/netmaker/mongoconn"
|
||||||
@@ -21,11 +22,10 @@ import (
|
|||||||
func groupHandlers(r *mux.Router) {
|
func groupHandlers(r *mux.Router) {
|
||||||
r.HandleFunc("/api/groups", securityCheck(http.HandlerFunc(getGroups))).Methods("GET")
|
r.HandleFunc("/api/groups", securityCheck(http.HandlerFunc(getGroups))).Methods("GET")
|
||||||
r.HandleFunc("/api/groups", securityCheck(http.HandlerFunc(createGroup))).Methods("POST")
|
r.HandleFunc("/api/groups", securityCheck(http.HandlerFunc(createGroup))).Methods("POST")
|
||||||
r.HandleFunc("/api/groups/{groupname}/keyupdate", securityCheck(http.HandlerFunc(keyUpdate))).Methods("POST")
|
|
||||||
r.HandleFunc("/api/groups/{groupname}", securityCheck(http.HandlerFunc(getGroup))).Methods("GET")
|
r.HandleFunc("/api/groups/{groupname}", securityCheck(http.HandlerFunc(getGroup))).Methods("GET")
|
||||||
r.HandleFunc("/api/groups/{groupname}/numnodes", securityCheck(http.HandlerFunc(getGroupNodeNumber))).Methods("GET")
|
|
||||||
r.HandleFunc("/api/groups/{groupname}", securityCheck(http.HandlerFunc(updateGroup))).Methods("PUT")
|
r.HandleFunc("/api/groups/{groupname}", securityCheck(http.HandlerFunc(updateGroup))).Methods("PUT")
|
||||||
r.HandleFunc("/api/groups/{groupname}", securityCheck(http.HandlerFunc(deleteGroup))).Methods("DELETE")
|
r.HandleFunc("/api/groups/{groupname}", securityCheck(http.HandlerFunc(deleteGroup))).Methods("DELETE")
|
||||||
|
r.HandleFunc("/api/groups/{groupname}/keyupdate", securityCheck(http.HandlerFunc(keyUpdate))).Methods("POST")
|
||||||
r.HandleFunc("/api/groups/{groupname}/keys", securityCheck(http.HandlerFunc(createAccessKey))).Methods("POST")
|
r.HandleFunc("/api/groups/{groupname}/keys", securityCheck(http.HandlerFunc(createAccessKey))).Methods("POST")
|
||||||
r.HandleFunc("/api/groups/{groupname}/keys", securityCheck(http.HandlerFunc(getAccessKeys))).Methods("GET")
|
r.HandleFunc("/api/groups/{groupname}/keys", securityCheck(http.HandlerFunc(getAccessKeys))).Methods("GET")
|
||||||
r.HandleFunc("/api/groups/{groupname}/keys/{name}", securityCheck(http.HandlerFunc(deleteAccessKey))).Methods("DELETE")
|
r.HandleFunc("/api/groups/{groupname}/keys/{name}", securityCheck(http.HandlerFunc(deleteAccessKey))).Methods("DELETE")
|
||||||
@@ -42,12 +42,16 @@ func securityCheck(next http.Handler) http.HandlerFunc {
|
|||||||
|
|
||||||
var params = mux.Vars(r)
|
var params = mux.Vars(r)
|
||||||
hasgroup := params["groupname"] != ""
|
hasgroup := params["groupname"] != ""
|
||||||
groupexists, _ := functions.GroupExists(params["groupname"])
|
groupexists, err := functions.GroupExists(params["groupname"])
|
||||||
if hasgroup && !groupexists {
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
} else if hasgroup && !groupexists {
|
||||||
errorResponse = models.ErrorResponse{
|
errorResponse = models.ErrorResponse{
|
||||||
Code: http.StatusNotFound, Message: "W1R3: This group does not exist.",
|
Code: http.StatusNotFound, Message: "W1R3: This group does not exist.",
|
||||||
}
|
}
|
||||||
returnErrorResponse(w, r, errorResponse)
|
returnErrorResponse(w, r, errorResponse)
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
bearerToken := r.Header.Get("Authorization")
|
bearerToken := r.Header.Get("Authorization")
|
||||||
@@ -68,6 +72,7 @@ func securityCheck(next http.Handler) http.HandlerFunc {
|
|||||||
Code: http.StatusUnauthorized, Message: "W1R3: You are unauthorized to access this endpoint.",
|
Code: http.StatusUnauthorized, Message: "W1R3: You are unauthorized to access this endpoint.",
|
||||||
}
|
}
|
||||||
returnErrorResponse(w, r, errorResponse)
|
returnErrorResponse(w, r, errorResponse)
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
@@ -85,15 +90,16 @@ func authenticateMaster(tokenString string) bool {
|
|||||||
//simple get all groups function
|
//simple get all groups function
|
||||||
func getGroups(w http.ResponseWriter, r *http.Request) {
|
func getGroups(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
//depends on list groups function
|
groups, err := functions.ListGroups()
|
||||||
//TODO: This is perhaps a more efficient way of handling ALL http handlers
|
|
||||||
//Take their primary logic and put in a separate function
|
|
||||||
//May be better since most http handler functionality is needed internally cross-method
|
|
||||||
//E.G. a method may need to check against all groups. But it cant call this function. That's why there's ListGroups
|
|
||||||
groups := functions.ListGroups()
|
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(groups)
|
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(groups)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateGroup(operation string, group models.Group) error {
|
func validateGroup(operation string, group models.Group) error {
|
||||||
@@ -105,14 +111,23 @@ func validateGroup(operation string, group models.Group) error {
|
|||||||
return isvalid
|
return isvalid
|
||||||
})
|
})
|
||||||
|
|
||||||
|
_ = v.RegisterValidation("privaterange_valid", func(fl validator.FieldLevel) bool {
|
||||||
|
isvalid := !*group.IsPrivate || functions.IsIpv4CIDR(fl.Field().String())
|
||||||
|
return isvalid
|
||||||
|
})
|
||||||
|
|
||||||
_ = v.RegisterValidation("nameid_valid", func(fl validator.FieldLevel) bool {
|
_ = v.RegisterValidation("nameid_valid", func(fl validator.FieldLevel) bool {
|
||||||
isFieldUnique := operation == "update" || functions.IsGroupNameUnique(fl.Field().String())
|
isFieldUnique := false
|
||||||
inGroupCharSet := functions.NameInGroupCharSet(fl.Field().String())
|
inCharSet := false
|
||||||
return isFieldUnique && inGroupCharSet
|
if operation == "update" { isFieldUnique = true } else{
|
||||||
|
isFieldUnique, _ = functions.IsGroupNameUnique(fl.Field().String())
|
||||||
|
inCharSet = functions.NameInGroupCharSet(fl.Field().String())
|
||||||
|
}
|
||||||
|
return isFieldUnique && inCharSet
|
||||||
})
|
})
|
||||||
|
|
||||||
_ = v.RegisterValidation("displayname_unique", func(fl validator.FieldLevel) bool {
|
_ = v.RegisterValidation("displayname_unique", func(fl validator.FieldLevel) bool {
|
||||||
isFieldUnique := functions.IsGroupDisplayNameUnique(fl.Field().String())
|
isFieldUnique, _ := functions.IsGroupDisplayNameUnique(fl.Field().String())
|
||||||
return isFieldUnique || operation == "update"
|
return isFieldUnique || operation == "update"
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -126,47 +141,6 @@ func validateGroup(operation string, group models.Group) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get number of nodes associated with a group
|
|
||||||
//May not be necessary, but I think the front end needs it? This should be reviewed after iteration 1
|
|
||||||
func getGroupNodeNumber(w http.ResponseWriter, r *http.Request) {
|
|
||||||
|
|
||||||
var params = mux.Vars(r)
|
|
||||||
|
|
||||||
count, err := GetGroupNodeNumber(params["groupname"])
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
var errorResponse = models.ErrorResponse{
|
|
||||||
Code: http.StatusInternalServerError, Message: "W1R3: Error retrieving nodes.",
|
|
||||||
}
|
|
||||||
returnErrorResponse(w, r, errorResponse)
|
|
||||||
} else {
|
|
||||||
json.NewEncoder(w).Encode(count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//This is haphazard
|
|
||||||
//I need a better folder structure
|
|
||||||
//maybe a functions/ folder and then a node.go, group.go, keys.go, misc.go
|
|
||||||
func GetGroupNodeNumber(groupName string) (int, error){
|
|
||||||
|
|
||||||
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
||||||
|
|
||||||
filter := bson.M{"group": groupName}
|
|
||||||
count, err := collection.CountDocuments(ctx, filter)
|
|
||||||
returncount := int(count)
|
|
||||||
|
|
||||||
//not sure if this is the right way of handling this error...
|
|
||||||
if err != nil {
|
|
||||||
return 9999, err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
return returncount, err
|
|
||||||
}
|
|
||||||
|
|
||||||
//Simple get group function
|
//Simple get group function
|
||||||
func getGroup(w http.ResponseWriter, r *http.Request) {
|
func getGroup(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
@@ -187,10 +161,10 @@ func getGroup(w http.ResponseWriter, r *http.Request) {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mongoconn.GetError(err, w)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode(group)
|
json.NewEncoder(w).Encode(group)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,8 +178,10 @@ func keyUpdate(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
group, err := functions.GetParentGroup(params["groupname"])
|
group, err := functions.GetParentGroup(params["groupname"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
}
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
group.KeyUpdateTimeStamp = time.Now().Unix()
|
group.KeyUpdateTimeStamp = time.Now().Unix()
|
||||||
|
|
||||||
@@ -234,16 +210,16 @@ func keyUpdate(w http.ResponseWriter, r *http.Request) {
|
|||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&group)
|
err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&group)
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if errN != nil {
|
if err != nil {
|
||||||
mongoconn.GetError(errN, w)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
fmt.Println(errN)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode(group)
|
json.NewEncoder(w).Encode(group)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,6 +234,7 @@ func updateGroup(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
group, err := functions.GetParentGroup(params["groupname"])
|
group, err := functions.GetParentGroup(params["groupname"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,6 +242,7 @@ func updateGroup(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
haschange := false
|
haschange := false
|
||||||
hasrangeupdate := false
|
hasrangeupdate := false
|
||||||
|
hasprivaterangeupdate := false
|
||||||
|
|
||||||
_ = json.NewDecoder(r.Body).Decode(&groupChange)
|
_ = json.NewDecoder(r.Body).Decode(&groupChange)
|
||||||
|
|
||||||
@@ -278,16 +256,12 @@ func updateGroup(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
err = validateGroup("update", groupChange)
|
err = validateGroup("update", groupChange)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//NOTE: Group.NameID is intentionally NOT editable. It acts as a static ID for the group.
|
||||||
//TODO: group.Name is not update-able
|
//DisplayName can be changed instead, which is what shows on the front end
|
||||||
//group.Name acts as the ID for the group and keeps it unique and searchable by nodes
|
|
||||||
//should consider renaming to group.ID
|
|
||||||
//Too lazy for now.
|
|
||||||
//DisplayName is the editable version and will not be used for node searches,
|
|
||||||
//but will be used by front end.
|
|
||||||
|
|
||||||
if groupChange.AddressRange != "" {
|
if groupChange.AddressRange != "" {
|
||||||
|
|
||||||
@@ -295,55 +269,64 @@ func updateGroup(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
var isAddressOK bool = functions.IsIpv4CIDR(groupChange.AddressRange)
|
var isAddressOK bool = functions.IsIpv4CIDR(groupChange.AddressRange)
|
||||||
if !isAddressOK {
|
if !isAddressOK {
|
||||||
|
err := errors.New("Invalid Range of " + groupChange.AddressRange + " for addresses.")
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
haschange = true
|
haschange = true
|
||||||
hasrangeupdate = true
|
hasrangeupdate = true
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if groupChange.PrivateRange != "" {
|
||||||
|
group.PrivateRange = groupChange.PrivateRange
|
||||||
|
|
||||||
if groupChange.DefaultListenPort != 0 {
|
var isAddressOK bool = functions.IsIpv4CIDR(groupChange.PrivateRange)
|
||||||
group.DefaultListenPort = groupChange.DefaultListenPort
|
if !isAddressOK {
|
||||||
|
err := errors.New("Invalid Range of " + groupChange.PrivateRange + " for internal addresses.")
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
haschange = true
|
haschange = true
|
||||||
|
hasprivaterangeupdate = true
|
||||||
|
}
|
||||||
|
if groupChange.IsPrivate != nil {
|
||||||
|
group.IsPrivate = groupChange.IsPrivate
|
||||||
|
}
|
||||||
|
if groupChange.DefaultListenPort != 0 {
|
||||||
|
group.DefaultListenPort = groupChange.DefaultListenPort
|
||||||
|
haschange = true
|
||||||
}
|
}
|
||||||
if groupChange.DefaultPreUp != "" {
|
if groupChange.DefaultPreUp != "" {
|
||||||
group.DefaultPreUp = groupChange.DefaultPreUp
|
group.DefaultPreUp = groupChange.DefaultPreUp
|
||||||
haschange = true
|
haschange = true
|
||||||
}
|
}
|
||||||
if groupChange.DefaultInterface != "" {
|
if groupChange.DefaultInterface != "" {
|
||||||
group.DefaultInterface = groupChange.DefaultInterface
|
group.DefaultInterface = groupChange.DefaultInterface
|
||||||
haschange = true
|
haschange = true
|
||||||
}
|
}
|
||||||
if groupChange.DefaultPostUp != "" {
|
if groupChange.DefaultPostUp != "" {
|
||||||
group.DefaultPostUp = groupChange.DefaultPostUp
|
group.DefaultPostUp = groupChange.DefaultPostUp
|
||||||
haschange = true
|
haschange = true
|
||||||
}
|
}
|
||||||
if groupChange.DefaultKeepalive != 0 {
|
if groupChange.DefaultKeepalive != 0 {
|
||||||
group.DefaultKeepalive = groupChange.DefaultKeepalive
|
group.DefaultKeepalive = groupChange.DefaultKeepalive
|
||||||
haschange = true
|
haschange = true
|
||||||
}
|
}
|
||||||
if groupChange.DisplayName != "" {
|
if groupChange.DisplayName != "" {
|
||||||
group.DisplayName = groupChange.DisplayName
|
group.DisplayName = groupChange.DisplayName
|
||||||
haschange = true
|
haschange = true
|
||||||
}
|
}
|
||||||
if groupChange.DefaultCheckInInterval != 0 {
|
if groupChange.DefaultCheckInInterval != 0 {
|
||||||
group.DefaultCheckInInterval = groupChange.DefaultCheckInInterval
|
group.DefaultCheckInInterval = groupChange.DefaultCheckInInterval
|
||||||
haschange = true
|
haschange = true
|
||||||
}
|
}
|
||||||
|
if groupChange.AllowManualSignUp != nil {
|
||||||
//TODO: Important. This doesn't work. This will create cases where we will
|
group.AllowManualSignUp = groupChange.AllowManualSignUp
|
||||||
//unintentionally go from allowing manual signup to disallowing
|
haschange = true
|
||||||
//need to find a smarter way
|
|
||||||
//maybe make into a text field
|
|
||||||
if groupChange.AllowManualSignUp != group.AllowManualSignUp {
|
|
||||||
group.AllowManualSignUp = groupChange.AllowManualSignUp
|
|
||||||
haschange = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
collection := mongoconn.Client.Database("netmaker").Collection("groups")
|
collection := mongoconn.Client.Database("netmaker").Collection("groups")
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
|
||||||
filter := bson.M{"nameid": params["groupname"]}
|
filter := bson.M{"nameid": params["groupname"]}
|
||||||
|
|
||||||
if haschange {
|
if haschange {
|
||||||
@@ -364,27 +347,44 @@ func updateGroup(w http.ResponseWriter, r *http.Request) {
|
|||||||
{"nodeslastmodified", group.NodesLastModified},
|
{"nodeslastmodified", group.NodesLastModified},
|
||||||
{"grouplastmodified", group.GroupLastModified},
|
{"grouplastmodified", group.GroupLastModified},
|
||||||
{"allowmanualsignup", group.AllowManualSignUp},
|
{"allowmanualsignup", group.AllowManualSignUp},
|
||||||
|
{"privaterange", group.PrivateRange},
|
||||||
|
{"isprivate", group.IsPrivate},
|
||||||
{"defaultcheckininterval", group.DefaultCheckInInterval},
|
{"defaultcheckininterval", group.DefaultCheckInInterval},
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&group)
|
err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&group)
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if errN != nil {
|
if err != nil {
|
||||||
mongoconn.GetError(errN, w)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
fmt.Println(errN)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//Cycles through nodes and gives them new IP's based on the new range
|
//Cycles through nodes and gives them new IP's based on the new range
|
||||||
//Pretty cool, but also pretty inefficient currently
|
//Pretty cool, but also pretty inefficient currently
|
||||||
if hasrangeupdate {
|
if hasrangeupdate {
|
||||||
_ = functions.UpdateGroupNodeAddresses(params["groupname"])
|
err = functions.UpdateGroupNodeAddresses(params["groupname"])
|
||||||
//json.NewEncoder(w).Encode(errG)
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
json.NewEncoder(w).Encode(group)
|
if hasprivaterangeupdate {
|
||||||
|
err = functions.UpdateGroupPrivateAddresses(params["groupname"])
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
returngroup, err := functions.GetParentGroup(group.NameID)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(returngroup)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Delete a group
|
//Delete a group
|
||||||
@@ -395,15 +395,12 @@ func deleteGroup(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
var params = mux.Vars(r)
|
var params = mux.Vars(r)
|
||||||
|
|
||||||
var errorResponse = models.ErrorResponse{
|
nodecount, err := functions.GetGroupNodeNumber(params["groupname"])
|
||||||
Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
|
if err != nil {
|
||||||
}
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
nodecount, err := GetGroupNodeNumber(params["groupname"])
|
} else if nodecount > 0 {
|
||||||
|
errorResponse := models.ErrorResponse{
|
||||||
//we dont wanna leave nodes hanging. They need a group!
|
|
||||||
if nodecount > 0 || err != nil {
|
|
||||||
errorResponse = models.ErrorResponse{
|
|
||||||
Code: http.StatusForbidden, Message: "W1R3: Node check failed. All nodes must be deleted before deleting group.",
|
Code: http.StatusForbidden, Message: "W1R3: Node check failed. All nodes must be deleted before deleting group.",
|
||||||
}
|
}
|
||||||
returnErrorResponse(w, r, errorResponse)
|
returnErrorResponse(w, r, errorResponse)
|
||||||
@@ -421,12 +418,12 @@ func deleteGroup(w http.ResponseWriter, r *http.Request) {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mongoconn.GetError(err, w)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode(deleteResult)
|
json.NewEncoder(w).Encode(deleteResult)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create a group
|
//Create a group
|
||||||
@@ -435,51 +432,50 @@ func createGroup(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
//TODO:
|
|
||||||
//This may be needed to get error response. May be why some errors dont work
|
|
||||||
//analyze different error responses and see what needs to be done
|
|
||||||
//commenting out for now
|
|
||||||
/*
|
|
||||||
var errorResponse = models.ErrorResponse{
|
|
||||||
Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
var group models.Group
|
var group models.Group
|
||||||
|
|
||||||
// we decode our body request params
|
// we decode our body request params
|
||||||
_ = json.NewDecoder(r.Body).Decode(&group)
|
err := json.NewDecoder(r.Body).Decode(&group)
|
||||||
|
|
||||||
//TODO: Not really doing good validation here. Same as createNode, updateNode, and updateGroup
|
|
||||||
//Need to implement some better validation across the board
|
|
||||||
err := validateGroup("create", group)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: Not really doing good validation here. Same as createNode, updateNode, and updateGroup
|
||||||
|
//Need to implement some better validation across the board
|
||||||
|
if group.IsPrivate == nil {
|
||||||
|
falsevar := false
|
||||||
|
group.IsPrivate = &falsevar
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validateGroup("create", group)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
group.SetDefaults()
|
group.SetDefaults()
|
||||||
group.SetNodesLastModified()
|
group.SetNodesLastModified()
|
||||||
group.SetGroupLastModified()
|
group.SetGroupLastModified()
|
||||||
group.KeyUpdateTimeStamp = time.Now().Unix()
|
group.KeyUpdateTimeStamp = time.Now().Unix()
|
||||||
|
|
||||||
|
|
||||||
collection := mongoconn.Client.Database("netmaker").Collection("groups")
|
collection := mongoconn.Client.Database("netmaker").Collection("groups")
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
|
||||||
|
|
||||||
// insert our group into the group table
|
// insert our group into the group table
|
||||||
result, err := collection.InsertOne(ctx, group)
|
result, err := collection.InsertOne(ctx, group)
|
||||||
_ = result
|
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mongoconn.GetError(err, w)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BEGIN KEY MANAGEMENT SECTION
|
// BEGIN KEY MANAGEMENT SECTION
|
||||||
// Consider a separate file for these controllers but I think same file is fine for now
|
|
||||||
|
|
||||||
|
|
||||||
//TODO: Very little error handling
|
//TODO: Very little error handling
|
||||||
@@ -496,10 +492,15 @@ func createAccessKey(w http.ResponseWriter, r *http.Request) {
|
|||||||
//start here
|
//start here
|
||||||
group, err := functions.GetParentGroup(params["groupname"])
|
group, err := functions.GetParentGroup(params["groupname"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = json.NewDecoder(r.Body).Decode(&accesskey)
|
err = json.NewDecoder(r.Body).Decode(&accesskey)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if accesskey.Name == "" {
|
if accesskey.Name == "" {
|
||||||
accesskey.Name = functions.GenKeyName()
|
accesskey.Name = functions.GenKeyName()
|
||||||
@@ -510,20 +511,18 @@ func createAccessKey(w http.ResponseWriter, r *http.Request) {
|
|||||||
if accesskey.Uses == 0 {
|
if accesskey.Uses == 0 {
|
||||||
accesskey.Uses = 1
|
accesskey.Uses = 1
|
||||||
}
|
}
|
||||||
gconf, errG := functions.GetGlobalConfig()
|
gconf, err := functions.GetGlobalConfig()
|
||||||
if errG != nil {
|
if err != nil {
|
||||||
mongoconn.GetError(errG, w)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
network := params["groupname"]
|
network := params["groupname"]
|
||||||
address := gconf.ServerGRPC + gconf.PortGRPC
|
address := gconf.ServerGRPC + gconf.PortGRPC
|
||||||
|
|
||||||
accessstringdec := address + "." + network + "." + accesskey.Value
|
accessstringdec := address + "." + network + "." + accesskey.Value
|
||||||
accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(accessstringdec))
|
accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(accessstringdec))
|
||||||
|
|
||||||
|
|
||||||
group.AccessKeys = append(group.AccessKeys, accesskey)
|
group.AccessKeys = append(group.AccessKeys, accesskey)
|
||||||
|
|
||||||
collection := mongoconn.Client.Database("netmaker").Collection("groups")
|
collection := mongoconn.Client.Database("netmaker").Collection("groups")
|
||||||
@@ -543,15 +542,17 @@ func createAccessKey(w http.ResponseWriter, r *http.Request) {
|
|||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&group)
|
err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&group)
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if errN != nil {
|
if err != nil {
|
||||||
mongoconn.GetError(errN, w)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Write([]byte(accesskey.AccessString))
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(accesskey)
|
||||||
|
//w.Write([]byte(accesskey.AccessString))
|
||||||
}
|
}
|
||||||
|
|
||||||
//pretty simple get
|
//pretty simple get
|
||||||
@@ -575,18 +576,19 @@ func getAccessKeys(w http.ResponseWriter, r *http.Request) {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mongoconn.GetError(err, w)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
keydata, keyerr := json.Marshal(group.AccessKeys)
|
keydata, err := json.Marshal(group.AccessKeys)
|
||||||
|
|
||||||
if keyerr != nil {
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
json.Unmarshal(keydata, &keys)
|
json.Unmarshal(keydata, &keys)
|
||||||
|
|
||||||
//json.NewEncoder(w).Encode(group.AccessKeys)
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode(keys)
|
json.NewEncoder(w).Encode(keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -604,9 +606,9 @@ func deleteAccessKey(w http.ResponseWriter, r *http.Request) {
|
|||||||
//start here
|
//start here
|
||||||
group, err := functions.GetParentGroup(params["groupname"])
|
group, err := functions.GetParentGroup(params["groupname"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//basically, turn the list of access keys into the list of access keys before and after the item
|
//basically, turn the list of access keys into the list of access keys before and after the item
|
||||||
//have not done any error handling for if there's like...1 item. I think it works? need to test.
|
//have not done any error handling for if there's like...1 item. I think it works? need to test.
|
||||||
for i := len(group.AccessKeys) - 1; i >= 0; i-- {
|
for i := len(group.AccessKeys) - 1; i >= 0; i-- {
|
||||||
@@ -632,12 +634,23 @@ func deleteAccessKey(w http.ResponseWriter, r *http.Request) {
|
|||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&group)
|
err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&group)
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if errN != nil {
|
if err != nil {
|
||||||
mongoconn.GetError(errN, w)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var keys []models.AccessKey
|
||||||
|
keydata, err := json.Marshal(group.AccessKeys)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
json.Unmarshal(keydata, &keys)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(keys)
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
|
"errors"
|
||||||
"github.com/gravitl/netmaker/functions"
|
"github.com/gravitl/netmaker/functions"
|
||||||
"github.com/gravitl/netmaker/mongoconn"
|
"github.com/gravitl/netmaker/mongoconn"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
@@ -10,7 +11,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
@@ -20,17 +20,18 @@ import (
|
|||||||
|
|
||||||
func nodeHandlers(r *mux.Router) {
|
func nodeHandlers(r *mux.Router) {
|
||||||
|
|
||||||
r.HandleFunc("/api/{group}/nodes", authorize(true, "group", http.HandlerFunc(getGroupNodes))).Methods("GET")
|
|
||||||
r.HandleFunc("/api/nodes", authorize(false, "master", http.HandlerFunc(getAllNodes))).Methods("GET")
|
r.HandleFunc("/api/nodes", authorize(false, "master", http.HandlerFunc(getAllNodes))).Methods("GET")
|
||||||
r.HandleFunc("/api/{group}/peerlist", authorize(true, "group", http.HandlerFunc(getPeerList))).Methods("GET")
|
r.HandleFunc("/api/nodes/{group}", authorize(true, "group", http.HandlerFunc(getGroupNodes))).Methods("GET")
|
||||||
r.HandleFunc("/api/{group}/lastmodified", authorize(true, "group", http.HandlerFunc(getLastModified))).Methods("GET")
|
r.HandleFunc("/api/nodes/{group}/{macaddress}", authorize(true, "node", http.HandlerFunc(getNode))).Methods("GET")
|
||||||
r.HandleFunc("/api/{group}/nodes/{macaddress}", authorize(true, "node", http.HandlerFunc(getNode))).Methods("GET")
|
r.HandleFunc("/api/nodes/{group}/{macaddress}", authorize(true, "node", http.HandlerFunc(updateNode))).Methods("PUT")
|
||||||
r.HandleFunc("/api/{group}/nodes", createNode).Methods("POST")
|
r.HandleFunc("/api/nodes/{group}/{macaddress}", authorize(true, "node", http.HandlerFunc(deleteNode))).Methods("DELETE")
|
||||||
r.HandleFunc("/api/{group}/nodes/{macaddress}", authorize(true, "node", http.HandlerFunc(updateNode))).Methods("PUT")
|
r.HandleFunc("/api/nodes/{group}/{macaddress}/checkin", authorize(true, "node", http.HandlerFunc(checkIn))).Methods("POST")
|
||||||
r.HandleFunc("/api/{group}/nodes/{macaddress}/checkin", authorize(true, "node", http.HandlerFunc(checkIn))).Methods("POST")
|
// r.HandleFunc("/api/nodes/{group}/{macaddress}/creategateway", authorize(true, "master", http.HandlerFunc(createGateway))).Methods("POST")
|
||||||
r.HandleFunc("/api/{group}/nodes/{macaddress}/uncordon", authorize(true, "master", http.HandlerFunc(uncordonNode))).Methods("POST")
|
// r.HandleFunc("/api/nodes/{group}/{macaddress}/deletegateway", authorize(true, "master", http.HandlerFunc(deleteGateway))).Methods("POST")
|
||||||
r.HandleFunc("/api/{group}/nodes/{macaddress}", authorize(true, "node", http.HandlerFunc(deleteNode))).Methods("DELETE")
|
r.HandleFunc("/api/nodes/{group}/{macaddress}/uncordon", authorize(true, "master", http.HandlerFunc(uncordonNode))).Methods("POST")
|
||||||
r.HandleFunc("/api/{group}/authenticate", authenticate).Methods("POST")
|
r.HandleFunc("/api/nodes/{group}/nodes", createNode).Methods("POST")
|
||||||
|
r.HandleFunc("/api/nodes/adm/{group}/lastmodified", authorize(true, "group", http.HandlerFunc(getLastModified))).Methods("GET")
|
||||||
|
r.HandleFunc("/api/nodes/adm/{group}/authenticate", authenticate).Methods("POST")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,6 +110,7 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
|
|||||||
returnErrorResponse(response, request, errorResponse)
|
returnErrorResponse(response, request, errorResponse)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
response.WriteHeader(http.StatusOK)
|
||||||
response.Header().Set("Content-Type", "application/json")
|
response.Header().Set("Content-Type", "application/json")
|
||||||
response.Write(successJSONResponse)
|
response.Write(successJSONResponse)
|
||||||
}
|
}
|
||||||
@@ -227,62 +229,6 @@ func authorize(groupCheck bool, authGroup string, next http.Handler) http.Handle
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Returns a list of peers in "plaintext" format, which can be piped straight to a file (peers.conf) on a local machine
|
|
||||||
//Not sure if it would be better to do that here or to let the client handle the formatting.
|
|
||||||
//TODO: May want to consider a different approach
|
|
||||||
func getPeerList(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
|
|
||||||
var nodes []models.Node
|
|
||||||
var params = mux.Vars(r)
|
|
||||||
|
|
||||||
//Connection mongoDB with mongoconn class
|
|
||||||
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
||||||
|
|
||||||
//Get all nodes in the relevant group which are NOT in pending state
|
|
||||||
filter := bson.M{"group": params["group"], "ispending": false}
|
|
||||||
cur, err := collection.Find(ctx, filter)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
mongoconn.GetError(err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the cursor once finished and cancel if it takes too long
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
for cur.Next(context.TODO()) {
|
|
||||||
|
|
||||||
var node models.Node
|
|
||||||
err := cur.Decode(&node)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the node to our node array
|
|
||||||
//maybe better to just return this? But then that's just GetNodes...
|
|
||||||
nodes = append(nodes, node)
|
|
||||||
}
|
|
||||||
|
|
||||||
//Uh oh, fatal error! This needs some better error handling
|
|
||||||
//TODO: needs appropriate error handling so the server doesnt shut down.
|
|
||||||
if err := cur.Err(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
//Writes output in the style familiar to WireGuard
|
|
||||||
//Get's piped to peers.conf locally after client request
|
|
||||||
for _, n := range nodes {
|
|
||||||
w.Write([]byte("[Peer] \n"))
|
|
||||||
w.Write([]byte("PublicKey = " + n.PublicKey + "\n"))
|
|
||||||
w.Write([]byte("AllowedIPs = " + n.Address + "/32" + "\n"))
|
|
||||||
w.Write([]byte("PersistentKeepalive = " + fmt.Sprint(n.PersistentKeepalive) + "\n"))
|
|
||||||
w.Write([]byte("Endpoint = " + n.Endpoint + ":" + fmt.Sprint(n.ListenPort) + "\n\n"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Gets all nodes associated with group, including pending nodes
|
//Gets all nodes associated with group, including pending nodes
|
||||||
func getGroupNodes(w http.ResponseWriter, r *http.Request) {
|
func getGroupNodes(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
@@ -300,10 +246,10 @@ func getGroupNodes(w http.ResponseWriter, r *http.Request) {
|
|||||||
//Filtering out the ID field cuz Dillon doesn't like it. May want to filter out other fields in the future
|
//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}))
|
cur, err := collection.Find(ctx, filter, options.Find().SetProjection(bson.M{"_id": 0}))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mongoconn.GetError(err, w)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@@ -317,8 +263,9 @@ func getGroupNodes(w http.ResponseWriter, r *http.Request) {
|
|||||||
var node models.ReturnNode
|
var node models.ReturnNode
|
||||||
|
|
||||||
err := cur.Decode(&node)
|
err := cur.Decode(&node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// add item our array of nodes
|
// add item our array of nodes
|
||||||
@@ -327,10 +274,12 @@ func getGroupNodes(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
//TODO: Another fatal error we should take care of.
|
//TODO: Another fatal error we should take care of.
|
||||||
if err := cur.Err(); err != nil {
|
if err := cur.Err(); err != nil {
|
||||||
log.Fatal(err)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//Returns all the nodes in JSON format
|
//Returns all the nodes in JSON format
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode(nodes)
|
json.NewEncoder(w).Encode(nodes)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -349,9 +298,8 @@ func getAllNodes(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// Filter out them ID's again
|
// Filter out them ID's again
|
||||||
cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
|
cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mongoconn.GetError(err, w)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,22 +309,23 @@ func getAllNodes(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
var node models.ReturnNode
|
var node models.ReturnNode
|
||||||
err := cur.Decode(&node)
|
err := cur.Decode(&node)
|
||||||
|
if err != nil {
|
||||||
//TODO: Fatal error
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
if err != nil {
|
return
|
||||||
log.Fatal(err)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// add node to our array
|
// add node to our array
|
||||||
nodes = append(nodes, node)
|
nodes = append(nodes, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Fatal error
|
//TODO: Fatal error
|
||||||
if err := cur.Err(); err != nil {
|
if err := cur.Err(); err != nil {
|
||||||
log.Fatal(err)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//Return all the nodes in JSON format
|
//Return all the nodes in JSON format
|
||||||
json.NewEncoder(w).Encode(nodes)
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(nodes)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,16 +371,18 @@ func checkIn(w http.ResponseWriter, r *http.Request) {
|
|||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&node)
|
err := collection.FindOneAndUpdate(ctx, filter, update).Decode(&node)
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if errN != nil {
|
if err != nil {
|
||||||
mongoconn.GetError(errN, w)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: check node last modified vs group last modified
|
//TODO: check node last modified vs group last modified
|
||||||
json.NewEncoder(w).Encode(node)
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(node)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,12 +394,11 @@ func getNode(w http.ResponseWriter, r *http.Request) {
|
|||||||
var params = mux.Vars(r)
|
var params = mux.Vars(r)
|
||||||
|
|
||||||
node, err := GetNode(params["macaddress"], params["group"])
|
node, err := GetNode(params["macaddress"], params["group"])
|
||||||
|
if err != nil {
|
||||||
if err != nil {
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
mongoconn.GetError(err, w)
|
return
|
||||||
return
|
}
|
||||||
}
|
w.WriteHeader(http.StatusOK)
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(node)
|
json.NewEncoder(w).Encode(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,11 +422,12 @@ func getLastModified(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
//log.Fatal(err)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write([]byte(string(group.NodesLastModified)))
|
w.Write([]byte(string(group.NodesLastModified)))
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -498,10 +449,12 @@ func createNode(w http.ResponseWriter, r *http.Request) {
|
|||||||
//Check if group exists first
|
//Check if group exists first
|
||||||
//TODO: This is inefficient. Let's find a better way.
|
//TODO: This is inefficient. Let's find a better way.
|
||||||
//Just a few rows down we grab the group anyway
|
//Just a few rows down we grab the group anyway
|
||||||
groupexists, errgroup := functions.GroupExists(groupName)
|
groupexists, err := functions.GroupExists(groupName)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
if !groupexists || errgroup != nil {
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
} else if !groupexists {
|
||||||
errorResponse = models.ErrorResponse{
|
errorResponse = models.ErrorResponse{
|
||||||
Code: http.StatusNotFound, Message: "W1R3: Group does not exist! ",
|
Code: http.StatusNotFound, Message: "W1R3: Group does not exist! ",
|
||||||
}
|
}
|
||||||
@@ -512,12 +465,20 @@ func createNode(w http.ResponseWriter, r *http.Request) {
|
|||||||
var node models.Node
|
var node models.Node
|
||||||
|
|
||||||
//get node from body of request
|
//get node from body of request
|
||||||
_ = json.NewDecoder(r.Body).Decode(&node)
|
err = json.NewDecoder(r.Body).Decode(&node)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
node.Group = groupName
|
node.Group = groupName
|
||||||
|
|
||||||
|
|
||||||
group, _ := node.GetGroup()
|
group, err := node.GetGroup()
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
//Check to see if key is valid
|
//Check to see if key is valid
|
||||||
//TODO: Triple inefficient!!! This is the third call to the DB we make for groups
|
//TODO: Triple inefficient!!! This is the third call to the DB we make for groups
|
||||||
@@ -537,16 +498,18 @@ func createNode(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := ValidateNode("create", groupName, node)
|
err = ValidateNode("create", groupName, node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
node, err = CreateNode(node, groupName)
|
node, err = CreateNode(node, groupName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode(node)
|
json.NewEncoder(w).Encode(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,8 +524,8 @@ func uncordonNode(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
node, err := functions.GetNodeByMacAddress(params["group"], params["macaddress"])
|
node, err := functions.GetNodeByMacAddress(params["group"], params["macaddress"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mongoconn.GetError(err, w)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
||||||
@@ -583,21 +546,71 @@ func uncordonNode(w http.ResponseWriter, r *http.Request) {
|
|||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&node)
|
err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&node)
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if errN != nil {
|
if err != nil {
|
||||||
mongoconn.GetError(errN, w)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Node " + node.Name + " uncordoned.")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode("SUCCESS")
|
||||||
|
}
|
||||||
|
|
||||||
|
func createGateway(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
var params = mux.Vars(r)
|
||||||
|
|
||||||
|
var node models.Node
|
||||||
|
|
||||||
|
node, err := functions.GetNodeByMacAddress(params["group"], params["macaddress"])
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
|
||||||
|
// Create filter
|
||||||
|
filter := bson.M{"macaddress": params["macaddress"], "group": params["group"]}
|
||||||
|
|
||||||
|
node.SetLastModified()
|
||||||
|
|
||||||
|
err = ValidateNode("create", params["group"], node)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare update model.
|
||||||
|
update := bson.D{
|
||||||
|
{"$set", bson.D{
|
||||||
|
{"ispending", false},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&node)
|
||||||
|
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println("Node " + node.Name + " uncordoned.")
|
fmt.Println("Node " + node.Name + " uncordoned.")
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode("SUCCESS")
|
json.NewEncoder(w).Encode("SUCCESS")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func updateNode(w http.ResponseWriter, r *http.Request) {
|
func updateNode(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
@@ -611,11 +624,12 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
|
|||||||
//start here
|
//start here
|
||||||
node, err := functions.GetNodeByMacAddress(params["group"], params["macaddress"])
|
node, err := functions.GetNodeByMacAddress(params["group"], params["macaddress"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
json.NewEncoder(w).Encode(err)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var nodechange models.Node
|
var nodechange models.Node
|
||||||
|
|
||||||
// we decode our body request params
|
// we decode our body request params
|
||||||
@@ -628,19 +642,17 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = ValidateNode("update", params["group"], nodechange)
|
err = ValidateNode("update", params["group"], nodechange)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
json.NewEncoder(w).Encode(err)
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
node, err = UpdateNode(nodechange, node)
|
node, err = UpdateNode(nodechange, node)
|
||||||
|
if err != nil {
|
||||||
if err != nil {
|
returnErrorResponse(w,r,formatError(err, "internal"))
|
||||||
json.NewEncoder(w).Encode(err)
|
return
|
||||||
return
|
}
|
||||||
}
|
w.WriteHeader(http.StatusOK)
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(node)
|
json.NewEncoder(w).Encode(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -655,29 +667,14 @@ func deleteNode(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
success, err := DeleteNode(params["macaddress"], params["group"])
|
success, err := DeleteNode(params["macaddress"], params["group"])
|
||||||
|
|
||||||
if err != nil || !success {
|
if err != nil {
|
||||||
json.NewEncoder(w).Encode("Could not delete node " + params["macaddress"])
|
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
|
return
|
||||||
}
|
}
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode(params["macaddress"] + " deleted.")
|
json.NewEncoder(w).Encode(params["macaddress"] + " deleted.")
|
||||||
}
|
}
|
||||||
|
|
||||||
//A fun lil method for handling errors with http
|
|
||||||
//Used in some cases but not others
|
|
||||||
//1. This should probably be an application-wide function
|
|
||||||
//2. All the API calls should probably be using this
|
|
||||||
//3. The mongoconn should probably use this.
|
|
||||||
//4. Need a consistent approach to error handling generally. Very haphazard at the moment
|
|
||||||
//TODO: This is important. All Handlers should be replying with appropriate error code.
|
|
||||||
func returnErrorResponse(response http.ResponseWriter, request *http.Request, errorMesage models.ErrorResponse) {
|
|
||||||
httpResponse := &models.ErrorResponse{Code: errorMesage.Code, Message: errorMesage.Message}
|
|
||||||
jsonResponse, err := json.Marshal(httpResponse)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
response.Header().Set("Content-Type", "application/json")
|
|
||||||
response.WriteHeader(errorMesage.Code)
|
|
||||||
response.Write(jsonResponse)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
49
controllers/responseHttp.go
Normal file
49
controllers/responseHttp.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gravitl/netmaker/models"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func formatError(err error, errType string) models.ErrorResponse {
|
||||||
|
|
||||||
|
var status = http.StatusInternalServerError
|
||||||
|
switch errType {
|
||||||
|
case "internal":
|
||||||
|
status = http.StatusInternalServerError
|
||||||
|
case "badrequest":
|
||||||
|
status = http.StatusBadRequest
|
||||||
|
case "notfound":
|
||||||
|
status = http.StatusNotFound
|
||||||
|
case "unauthorized":
|
||||||
|
status = http.StatusUnauthorized
|
||||||
|
case "forbidden":
|
||||||
|
status = http.StatusForbidden
|
||||||
|
default:
|
||||||
|
status = http.StatusInternalServerError
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = models.ErrorResponse{
|
||||||
|
Message: err.Error(),
|
||||||
|
Code: status,
|
||||||
|
}
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
func returnSuccessResponse(response http.ResponseWriter, request *http.Request, errorMesage models.ErrorResponse) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func returnErrorResponse(response http.ResponseWriter, request *http.Request, errorMessage models.ErrorResponse) {
|
||||||
|
httpResponse := &models.ErrorResponse{Code: errorMessage.Code, Message: errorMessage.Message}
|
||||||
|
jsonResponse, err := json.Marshal(httpResponse)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(errorMessage)
|
||||||
|
response.Header().Set("Content-Type", "application/json")
|
||||||
|
response.WriteHeader(errorMessage.Code)
|
||||||
|
response.Write(jsonResponse)
|
||||||
|
}
|
@@ -21,12 +21,12 @@ import (
|
|||||||
|
|
||||||
func userHandlers(r *mux.Router) {
|
func userHandlers(r *mux.Router) {
|
||||||
|
|
||||||
r.HandleFunc("/users/hasadmin", hasAdmin).Methods("GET")
|
r.HandleFunc("/api/users/adm/hasadmin", hasAdmin).Methods("GET")
|
||||||
r.HandleFunc("/users/createadmin", createAdmin).Methods("POST")
|
r.HandleFunc("/api/users/adm/createadmin", createAdmin).Methods("POST")
|
||||||
r.HandleFunc("/users/{username}", authorizeUser(http.HandlerFunc(updateUser))).Methods("PUT")
|
r.HandleFunc("/api/users/adm/authenticate", authenticateUser).Methods("POST")
|
||||||
r.HandleFunc("/users/{username}", authorizeUser(http.HandlerFunc(deleteUser))).Methods("DELETE")
|
r.HandleFunc("/api/users/{username}", authorizeUser(http.HandlerFunc(updateUser))).Methods("PUT")
|
||||||
r.HandleFunc("/users/{username}", authorizeUser(http.HandlerFunc(getUser))).Methods("GET")
|
r.HandleFunc("/api/users/{username}", authorizeUser(http.HandlerFunc(deleteUser))).Methods("DELETE")
|
||||||
r.HandleFunc("/users/authenticate", authenticateUser).Methods("POST")
|
r.HandleFunc("/api/users/{username}", authorizeUser(http.HandlerFunc(getUser))).Methods("GET")
|
||||||
}
|
}
|
||||||
|
|
||||||
//Node authenticates using its password and retrieves a JWT for authorization.
|
//Node authenticates using its password and retrieves a JWT for authorization.
|
||||||
|
@@ -12,7 +12,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"strings"
|
"strings"
|
||||||
"log"
|
|
||||||
"net"
|
"net"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/mongoconn"
|
"github.com/gravitl/netmaker/mongoconn"
|
||||||
@@ -171,13 +170,62 @@ func UpdateGroupNodeAddresses(groupName string) error {
|
|||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
//TODO TODO TODO!!!!!
|
||||||
|
func UpdateGroupPrivateAddresses(groupName string) error {
|
||||||
|
|
||||||
|
//Connection mongoDB with mongoconn class
|
||||||
|
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
|
||||||
|
filter := bson.M{"group": groupName}
|
||||||
|
cur, err := collection.Find(ctx, filter)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
for cur.Next(context.TODO()) {
|
||||||
|
|
||||||
|
var node models.Node
|
||||||
|
|
||||||
|
err := cur.Decode(&node)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("error in node address assignment!")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ipaddr, iperr := UniqueAddress(groupName)
|
||||||
|
if iperr != nil {
|
||||||
|
fmt.Println("error in node address assignment!")
|
||||||
|
return iperr
|
||||||
|
}
|
||||||
|
|
||||||
|
filter := bson.M{"macaddress": node.MacAddress}
|
||||||
|
update := bson.D{{"$set", bson.D{{"address", ipaddr}}}}
|
||||||
|
|
||||||
|
errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&node)
|
||||||
|
|
||||||
|
defer cancel()
|
||||||
|
if errN != nil {
|
||||||
|
return errN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
//Checks to see if any other groups have the same name (id)
|
//Checks to see if any other groups have the same name (id)
|
||||||
func IsGroupNameUnique(name string) bool {
|
func IsGroupNameUnique(name string) (bool, error ){
|
||||||
|
|
||||||
isunique := true
|
isunique := true
|
||||||
|
|
||||||
dbs := ListGroups()
|
dbs, err := ListGroups()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < len(dbs); i++ {
|
for i := 0; i < len(dbs); i++ {
|
||||||
|
|
||||||
@@ -186,14 +234,18 @@ func IsGroupNameUnique(name string) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return isunique
|
return isunique, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsGroupDisplayNameUnique(name string) bool {
|
func IsGroupDisplayNameUnique(name string) (bool, error){
|
||||||
|
|
||||||
isunique := true
|
isunique := true
|
||||||
|
|
||||||
dbs := ListGroups()
|
dbs, err := ListGroups()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for i := 0; i < len(dbs); i++ {
|
for i := 0; i < len(dbs); i++ {
|
||||||
|
|
||||||
@@ -202,12 +254,34 @@ func IsGroupDisplayNameUnique(name string) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return isunique
|
return isunique, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetGroupNodeNumber(groupName string) (int, error){
|
||||||
|
|
||||||
|
collection := mongoconn.Client.Database("wirecat").Collection("nodes")
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
|
||||||
|
filter := bson.M{"group": groupName}
|
||||||
|
count, err := collection.CountDocuments(ctx, filter)
|
||||||
|
returncount := int(count)
|
||||||
|
|
||||||
|
//not sure if this is the right way of handling this error...
|
||||||
|
if err != nil {
|
||||||
|
return 9999, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
return returncount, err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//Kind of a weird name. Should just be GetGroups I think. Consider changing.
|
//Kind of a weird name. Should just be GetGroups I think. Consider changing.
|
||||||
//Anyway, returns all the groups
|
//Anyway, returns all the groups
|
||||||
func ListGroups() []models.Group{
|
func ListGroups() ([]models.Group, error){
|
||||||
|
|
||||||
var groups []models.Group
|
var groups []models.Group
|
||||||
|
|
||||||
collection := mongoconn.Client.Database("netmaker").Collection("groups")
|
collection := mongoconn.Client.Database("netmaker").Collection("groups")
|
||||||
@@ -217,7 +291,7 @@ func ListGroups() []models.Group{
|
|||||||
cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
|
cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return groups
|
return groups, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -227,7 +301,7 @@ func ListGroups() []models.Group{
|
|||||||
var group models.Group
|
var group models.Group
|
||||||
err := cur.Decode(&group)
|
err := cur.Decode(&group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return groups, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// add group our array
|
// add group our array
|
||||||
@@ -235,10 +309,10 @@ func ListGroups() []models.Group{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := cur.Err(); err != nil {
|
if err := cur.Err(); err != nil {
|
||||||
log.Fatal(err)
|
return groups, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return groups
|
return groups, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//Checks to see if access key is valid
|
//Checks to see if access key is valid
|
||||||
|
@@ -24,6 +24,8 @@ type Group struct {
|
|||||||
DefaultSaveConfig *bool `json:"defaultsaveconfig" bson:"defaultsaveconfig"`
|
DefaultSaveConfig *bool `json:"defaultsaveconfig" bson:"defaultsaveconfig"`
|
||||||
AccessKeys []AccessKey `json:"accesskeys" bson:"accesskeys"`
|
AccessKeys []AccessKey `json:"accesskeys" bson:"accesskeys"`
|
||||||
AllowManualSignUp *bool `json:"allowmanualsignup" bson:"allowmanualsignup"`
|
AllowManualSignUp *bool `json:"allowmanualsignup" bson:"allowmanualsignup"`
|
||||||
|
IsPrivate *bool `json:"isprivate" bson:"isprivate"`
|
||||||
|
PrivateRange string `json:"privaterange" bson:"privaterange" validate:"privaterange_valid"`
|
||||||
DefaultCheckInInterval int32 `json:"checkininterval,omitempty" bson:"checkininterval,omitempty" validate:"omitempty,numeric,min=1,max=100000"`
|
DefaultCheckInInterval int32 `json:"checkininterval,omitempty" bson:"checkininterval,omitempty" validate:"omitempty,numeric,min=1,max=100000"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -99,3 +99,10 @@ type PeersResponse struct {
|
|||||||
KeepAlive int32 `json:"persistentkeepalive" bson:"persistentkeepalive"`
|
KeepAlive int32 `json:"persistentkeepalive" bson:"persistentkeepalive"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GatewayRequest struct {
|
||||||
|
RangeString string `json:"rangestring" bson:"rangestring"`
|
||||||
|
Ranges []string `json:"ranges" bson:"ranges"`
|
||||||
|
Interface string `json:"interface" bson:"interface"`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -78,7 +78,9 @@ func Install(accesskey string, password string, server string, group string, noa
|
|||||||
tserver := ""
|
tserver := ""
|
||||||
tnetwork := ""
|
tnetwork := ""
|
||||||
tkey := ""
|
tkey := ""
|
||||||
|
trange := ""
|
||||||
|
var localrange *net.IPNet
|
||||||
|
islocal := false
|
||||||
if FileExists("/etc/systemd/system/netclient-"+group+".timer") ||
|
if FileExists("/etc/systemd/system/netclient-"+group+".timer") ||
|
||||||
FileExists("/etc/netclient/netconfig-"+group) {
|
FileExists("/etc/netclient/netconfig-"+group) {
|
||||||
err := errors.New("ALREADY_INSTALLED. Netclient appears to already be installed for network " + group + ". To re-install, please remove by executing 'sudo netclient -c remove -n " + group + "'. Then re-run the install command.")
|
err := errors.New("ALREADY_INSTALLED. Netclient appears to already be installed for network " + group + ". To re-install, please remove by executing 'sudo netclient -c remove -n " + group + "'. Then re-run the install command.")
|
||||||
@@ -95,13 +97,29 @@ func Install(accesskey string, password string, server string, group string, noa
|
|||||||
tserver = tokenvals[0]
|
tserver = tokenvals[0]
|
||||||
tnetwork = tokenvals[1]
|
tnetwork = tokenvals[1]
|
||||||
tkey = tokenvals[2]
|
tkey = tokenvals[2]
|
||||||
server = tserver
|
trange = tokenvals[3]
|
||||||
group = tnetwork
|
if server == "" {
|
||||||
accesskey = tkey
|
server = tserver
|
||||||
|
}
|
||||||
|
if group == "" {
|
||||||
|
group = tnetwork
|
||||||
|
}
|
||||||
|
if accesskey == "" {
|
||||||
|
accesskey = tkey
|
||||||
|
}
|
||||||
|
if trange != "" {
|
||||||
|
islocal = true
|
||||||
|
_, localrange, err = net.ParseCIDR(trange)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
trange = "Not a local network. Will use public address for endpoint."
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println("Decoded values from token:")
|
fmt.Println("Decoded values from token:")
|
||||||
fmt.Println(" Server: " + tserver)
|
fmt.Println(" Server: " + tserver)
|
||||||
fmt.Println(" Network: " + tnetwork)
|
fmt.Println(" Network: " + tnetwork)
|
||||||
fmt.Println(" Key: " + tkey)
|
fmt.Println(" Key: " + tkey)
|
||||||
|
fmt.Println(" Local Range: " + localrange.String())
|
||||||
}
|
}
|
||||||
wgclient, err := wgctrl.New()
|
wgclient, err := wgctrl.New()
|
||||||
|
|
||||||
@@ -125,9 +143,6 @@ func Install(accesskey string, password string, server string, group string, noa
|
|||||||
server = servercfg.Address
|
server = servercfg.Address
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tserver != "" {
|
|
||||||
server = tserver
|
|
||||||
}
|
|
||||||
fmt.Println(" Server: " + server)
|
fmt.Println(" Server: " + server)
|
||||||
|
|
||||||
if accesskey == "" {
|
if accesskey == "" {
|
||||||
@@ -137,9 +152,6 @@ func Install(accesskey string, password string, server string, group string, noa
|
|||||||
accesskey = servercfg.AccessKey
|
accesskey = servercfg.AccessKey
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tkey != "" {
|
|
||||||
accesskey = tkey
|
|
||||||
}
|
|
||||||
fmt.Println(" AccessKey: " + accesskey)
|
fmt.Println(" AccessKey: " + accesskey)
|
||||||
err = config.WriteServer(server, accesskey, group)
|
err = config.WriteServer(server, accesskey, group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -167,9 +179,6 @@ func Install(accesskey string, password string, server string, group string, noa
|
|||||||
group = nodecfg.Group
|
group = nodecfg.Group
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tnetwork != "" {
|
|
||||||
group = tnetwork
|
|
||||||
}
|
|
||||||
fmt.Println(" Group: " + group)
|
fmt.Println(" Group: " + group)
|
||||||
|
|
||||||
var macaddress string
|
var macaddress string
|
||||||
@@ -218,13 +227,22 @@ func Install(accesskey string, password string, server string, group string, noa
|
|||||||
if !found {
|
if !found {
|
||||||
ip = v.IP
|
ip = v.IP
|
||||||
local = ip.String()
|
local = ip.String()
|
||||||
found = true
|
if islocal {
|
||||||
|
found = localrange.Contains(ip)
|
||||||
|
} else {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case *net.IPAddr:
|
case *net.IPAddr:
|
||||||
if !found {
|
if !found {
|
||||||
ip = v.IP
|
ip = v.IP
|
||||||
local = ip.String()
|
local = ip.String()
|
||||||
found = true
|
if islocal {
|
||||||
|
found = localrange.Contains(ip)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user