externalHttpController.go.backup 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. package controller
  2. import (
  3. "context"
  4. "encoding/json"
  5. "errors"
  6. // "fmt"
  7. "net/http"
  8. "time"
  9. "github.com/gorilla/mux"
  10. "github.com/gravitl/netmaker/functions"
  11. "github.com/gravitl/netmaker/models"
  12. "github.com/gravitl/netmaker/mongoconn"
  13. "go.mongodb.org/mongo-driver/bson"
  14. "go.mongodb.org/mongo-driver/mongo/options"
  15. // "github.com/skip2/go-qrcode"
  16. )
  17. func externalHandlers(r *mux.Router) {
  18. r.HandleFunc("/api/externals", securityCheck(http.HandlerFunc(getAllExternals))).Methods("GET")
  19. r.HandleFunc("/api/externals/{network}", securityCheck(http.HandlerFunc(getNetworkExternals))).Methods("GET")
  20. r.HandleFunc("/api/externals/{network}/{clientid}", securityCheck(http.HandlerFunc(getExternal))).Methods("GET")
  21. r.HandleFunc("/api/externals/{network}/{clientid}/qr", securityCheck(http.HandlerFunc(getExternal))).Methods("GET")
  22. r.HandleFunc("/api/externals/{network}/{ingressgateway}", securityCheck(http.HandlerFunc(getExternal))).Methods("GET")
  23. r.HandleFunc("/api/externals/{network}/{clientid}", securityCheck(http.HandlerFunc(updateExternal))).Methods("PUT")
  24. r.HandleFunc("/api/externals/{network}/{clientid}", securityCheck(http.HandlerFunc(deleteExternal))).Methods("DELETE")
  25. r.HandleFunc("/api/externals/{network}", securityCheck(http.HandlerFunc(createExternal))).Methods("POST")
  26. }
  27. //Gets all nodes associated with network, including pending nodes
  28. func getNetworkExternals(w http.ResponseWriter, r *http.Request) {
  29. w.Header().Set("Content-Type", "application/json")
  30. var nodes []models.External
  31. var params = mux.Vars(r)
  32. nodes, err := GetNetworkExternals(params["network"])
  33. if err != nil {
  34. returnErrorResponse(w, r, formatError(err, "internal"))
  35. return
  36. }
  37. //Returns all the nodes in JSON format
  38. w.WriteHeader(http.StatusOK)
  39. json.NewEncoder(w).Encode(nodes)
  40. }
  41. func GetNetworkExternals(network string) ([]models.External, error) {
  42. var nodes []models.External
  43. collection := mongoconn.Client.Database("netmaker").Collection("nodes")
  44. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  45. filter := bson.M{"network": network}
  46. //Filtering out the ID field cuz Dillon doesn't like it. May want to filter out other fields in the future
  47. cur, err := collection.Find(ctx, filter, options.Find().SetProjection(bson.M{"_id": 0}))
  48. if err != nil {
  49. return []models.External{}, err
  50. }
  51. defer cancel()
  52. for cur.Next(context.TODO()) {
  53. //Using a different model for the ReturnExternal (other than regular node).
  54. //Either we should do this for ALL structs (so Networks and Keys)
  55. //OR we should just use the original struct
  56. //My preference is to make some new return structs
  57. //TODO: Think about this. Not an immediate concern. Just need to get some consistency eventually
  58. var node models.External
  59. err := cur.Decode(&node)
  60. if err != nil {
  61. return []models.External{}, err
  62. }
  63. // add item our array of nodes
  64. nodes = append(nodes, node)
  65. }
  66. //TODO: Another fatal error we should take care of.
  67. if err := cur.Err(); err != nil {
  68. return []models.External{}, err
  69. }
  70. return nodes, nil
  71. }
  72. //A separate function to get all nodes, not just nodes for a particular network.
  73. //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
  74. func getAllExternals(w http.ResponseWriter, r *http.Request) {
  75. w.Header().Set("Content-Type", "application/json")
  76. nodes, err := functions.GetAllExternals()
  77. if err != nil {
  78. returnErrorResponse(w, r, formatError(err, "internal"))
  79. return
  80. }
  81. //Return all the nodes in JSON format
  82. w.WriteHeader(http.StatusOK)
  83. json.NewEncoder(w).Encode(nodes)
  84. }
  85. //Get an individual node. Nothin fancy here folks.
  86. func getExternal(w http.ResponseWriter, r *http.Request) {
  87. // set header.
  88. w.Header().Set("Content-Type", "application/json")
  89. var params = mux.Vars(r)
  90. var node models.Node
  91. collection := mongoconn.Client.Database("netmaker").Collection("nodes")
  92. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  93. filter := bson.M{"macaddress": params["macaddress"], "network": params["network"]}
  94. err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&node)
  95. defer cancel()
  96. w.WriteHeader(http.StatusOK)
  97. json.NewEncoder(w).Encode(node)
  98. }
  99. //This one's a doozy
  100. //To create a node
  101. //Must have valid key and be unique
  102. func createExternal(w http.ResponseWriter, r *http.Request) {
  103. w.Header().Set("Content-Type", "application/json")
  104. var params = mux.Vars(r)
  105. var errorResponse = models.ErrorResponse{
  106. Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
  107. }
  108. networkName := params["network"]
  109. //Check if network exists first
  110. //TODO: This is inefficient. Let's find a better way.
  111. //Just a few rows down we grab the network anyway
  112. networkexists, err := functions.NetworkExists(networkName)
  113. if err != nil {
  114. returnErrorResponse(w, r, formatError(err, "internal"))
  115. return
  116. } else if !networkexists {
  117. errorResponse = models.ErrorResponse{
  118. Code: http.StatusNotFound, Message: "W1R3: Network does not exist! ",
  119. }
  120. returnErrorResponse(w, r, errorResponse)
  121. return
  122. }
  123. var external models.External
  124. //get node from body of request
  125. err = json.NewDecoder(r.Body).Decode(&external)
  126. if err != nil {
  127. returnErrorResponse(w, r, formatError(err, "internal"))
  128. return
  129. }
  130. err = ValidateExternalCreate(external)
  131. if err != nil {
  132. returnErrorResponse(w, r, formatError(err, "badrequest"))
  133. return
  134. }
  135. node, err = CreateExternal(node, networkName)
  136. if err != nil {
  137. returnErrorResponse(w, r, formatError(err, "internal"))
  138. return
  139. }
  140. w.WriteHeader(http.StatusOK)
  141. json.NewEncoder(w).Encode(node)
  142. }
  143. func updateExternal(w http.ResponseWriter, r *http.Request) {
  144. w.Header().Set("Content-Type", "application/json")
  145. var params = mux.Vars(r)
  146. //Get id from parameters
  147. //id, _ := primitive.ObjectIDFromHex(params["id"])
  148. var node models.External
  149. //start here
  150. node, err := functions.GetExternalByMacAddress(params["network"], params["macaddress"])
  151. if err != nil {
  152. returnErrorResponse(w, r, formatError(err, "internal"))
  153. return
  154. }
  155. var nodechange models.ExternalUpdate
  156. // we decode our body request params
  157. _ = json.NewDecoder(r.Body).Decode(&nodechange)
  158. if nodechange.Network == "" {
  159. nodechange.Network = node.Network
  160. }
  161. if nodechange.MacAddress == "" {
  162. nodechange.MacAddress = node.MacAddress
  163. }
  164. err = ValidateExternalUpdate(params["network"], nodechange)
  165. if err != nil {
  166. returnErrorResponse(w, r, formatError(err, "badrequest"))
  167. return
  168. }
  169. node, err = UpdateExternal(nodechange, node)
  170. if err != nil {
  171. returnErrorResponse(w, r, formatError(err, "internal"))
  172. return
  173. }
  174. w.WriteHeader(http.StatusOK)
  175. json.NewEncoder(w).Encode(node)
  176. }
  177. //Delete a node
  178. //Pretty straightforward
  179. func deleteExternal(w http.ResponseWriter, r *http.Request) {
  180. // Set header
  181. w.Header().Set("Content-Type", "application/json")
  182. // get params
  183. var params = mux.Vars(r)
  184. success, err := DeleteExternal(params["macaddress"], params["network"])
  185. if err != nil {
  186. returnErrorResponse(w, r, formatError(err, "internal"))
  187. return
  188. } else if !success {
  189. err = errors.New("Could not delete node " + params["macaddress"])
  190. returnErrorResponse(w, r, formatError(err, "internal"))
  191. return
  192. }
  193. returnSuccessResponse(w, r, params["macaddress"]+" deleted.")
  194. }