node.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. package controller
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "strings"
  6. "github.com/gorilla/mux"
  7. "github.com/gravitl/netmaker/database"
  8. "github.com/gravitl/netmaker/functions"
  9. "github.com/gravitl/netmaker/logger"
  10. "github.com/gravitl/netmaker/logic"
  11. "github.com/gravitl/netmaker/models"
  12. "github.com/gravitl/netmaker/mq"
  13. "github.com/gravitl/netmaker/servercfg"
  14. "golang.org/x/crypto/bcrypt"
  15. )
  16. func nodeHandlers(r *mux.Router) {
  17. r.HandleFunc("/api/nodes", authorize(false, "user", http.HandlerFunc(getAllNodes))).Methods("GET")
  18. r.HandleFunc("/api/nodes/{network}", authorize(true, "network", http.HandlerFunc(getNetworkNodes))).Methods("GET")
  19. r.HandleFunc("/api/nodes/{network}/{nodeid}", authorize(true, "node", http.HandlerFunc(getNode))).Methods("GET")
  20. r.HandleFunc("/api/nodes/{network}/{nodeid}", authorize(true, "node", http.HandlerFunc(updateNode))).Methods("PUT")
  21. r.HandleFunc("/api/nodes/{network}/{nodeid}", authorize(true, "node", http.HandlerFunc(deleteNode))).Methods("DELETE")
  22. r.HandleFunc("/api/nodes/{network}/{nodeid}/createrelay", authorize(true, "user", http.HandlerFunc(createRelay))).Methods("POST")
  23. r.HandleFunc("/api/nodes/{network}/{nodeid}/deleterelay", authorize(true, "user", http.HandlerFunc(deleteRelay))).Methods("DELETE")
  24. r.HandleFunc("/api/nodes/{network}/{nodeid}/creategateway", authorize(true, "user", http.HandlerFunc(createEgressGateway))).Methods("POST")
  25. r.HandleFunc("/api/nodes/{network}/{nodeid}/deletegateway", authorize(true, "user", http.HandlerFunc(deleteEgressGateway))).Methods("DELETE")
  26. r.HandleFunc("/api/nodes/{network}/{nodeid}/createingress", securityCheck(false, http.HandlerFunc(createIngressGateway))).Methods("POST")
  27. r.HandleFunc("/api/nodes/{network}/{nodeid}/deleteingress", securityCheck(false, http.HandlerFunc(deleteIngressGateway))).Methods("DELETE")
  28. r.HandleFunc("/api/nodes/{network}/{nodeid}/approve", authorize(true, "user", http.HandlerFunc(uncordonNode))).Methods("POST")
  29. r.HandleFunc("/api/nodes/{network}", createNode).Methods("POST")
  30. r.HandleFunc("/api/nodes/adm/{network}/lastmodified", authorize(true, "network", http.HandlerFunc(getLastModified))).Methods("GET")
  31. r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods("POST")
  32. }
  33. func authenticate(response http.ResponseWriter, request *http.Request) {
  34. var params = mux.Vars(request)
  35. networkname := params["network"]
  36. var authRequest models.AuthParams
  37. var result models.Node
  38. var errorResponse = models.ErrorResponse{
  39. Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
  40. }
  41. decoder := json.NewDecoder(request.Body)
  42. decoderErr := decoder.Decode(&authRequest)
  43. defer request.Body.Close()
  44. if decoderErr != nil {
  45. errorResponse.Code = http.StatusBadRequest
  46. errorResponse.Message = decoderErr.Error()
  47. returnErrorResponse(response, request, errorResponse)
  48. return
  49. } else {
  50. errorResponse.Code = http.StatusBadRequest
  51. if authRequest.MacAddress == "" {
  52. errorResponse.Message = "W1R3: MacAddress can't be empty"
  53. returnErrorResponse(response, request, errorResponse)
  54. return
  55. } else if authRequest.Password == "" {
  56. errorResponse.Message = "W1R3: Password can't be empty"
  57. returnErrorResponse(response, request, errorResponse)
  58. return
  59. } else {
  60. collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
  61. if err != nil {
  62. errorResponse.Code = http.StatusBadRequest
  63. errorResponse.Message = err.Error()
  64. returnErrorResponse(response, request, errorResponse)
  65. return
  66. }
  67. for _, value := range collection {
  68. if err := json.Unmarshal([]byte(value), &result); err != nil {
  69. continue
  70. }
  71. if (result.ID == authRequest.ID || result.MacAddress == authRequest.MacAddress) && result.IsPending != "yes" && result.Network == networkname {
  72. break
  73. }
  74. }
  75. if err != nil {
  76. errorResponse.Code = http.StatusBadRequest
  77. errorResponse.Message = err.Error()
  78. returnErrorResponse(response, request, errorResponse)
  79. return
  80. }
  81. err = bcrypt.CompareHashAndPassword([]byte(result.Password), []byte(authRequest.Password))
  82. if err != nil {
  83. errorResponse.Code = http.StatusBadRequest
  84. errorResponse.Message = err.Error()
  85. returnErrorResponse(response, request, errorResponse)
  86. return
  87. } else {
  88. tokenString, _ := logic.CreateJWT(authRequest.ID, authRequest.MacAddress, result.Network)
  89. if tokenString == "" {
  90. errorResponse.Code = http.StatusBadRequest
  91. errorResponse.Message = "Could not create Token"
  92. returnErrorResponse(response, request, errorResponse)
  93. return
  94. }
  95. var successResponse = models.SuccessResponse{
  96. Code: http.StatusOK,
  97. Message: "W1R3: Device " + authRequest.MacAddress + " Authorized",
  98. Response: models.SuccessfulLoginResponse{
  99. AuthToken: tokenString,
  100. MacAddress: authRequest.MacAddress,
  101. },
  102. }
  103. successJSONResponse, jsonError := json.Marshal(successResponse)
  104. if jsonError != nil {
  105. errorResponse.Code = http.StatusBadRequest
  106. errorResponse.Message = err.Error()
  107. returnErrorResponse(response, request, errorResponse)
  108. return
  109. }
  110. response.WriteHeader(http.StatusOK)
  111. response.Header().Set("Content-Type", "application/json")
  112. response.Write(successJSONResponse)
  113. }
  114. }
  115. }
  116. }
  117. //The middleware for most requests to the API
  118. //They all pass through here first
  119. //This will validate the JWT (or check for master token)
  120. //This will also check against the authNetwork and make sure the node should be accessing that endpoint,
  121. //even if it's technically ok
  122. //This is kind of a poor man's RBAC. There's probably a better/smarter way.
  123. //TODO: Consider better RBAC implementations
  124. func authorize(networkCheck bool, authNetwork string, next http.Handler) http.HandlerFunc {
  125. return func(w http.ResponseWriter, r *http.Request) {
  126. var errorResponse = models.ErrorResponse{
  127. Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
  128. }
  129. var params = mux.Vars(r)
  130. networkexists, _ := functions.NetworkExists(params["network"])
  131. //check that the request is for a valid network
  132. //if (networkCheck && !networkexists) || err != nil {
  133. if networkCheck && !networkexists {
  134. errorResponse = models.ErrorResponse{
  135. Code: http.StatusNotFound, Message: "W1R3: This network does not exist. ",
  136. }
  137. returnErrorResponse(w, r, errorResponse)
  138. return
  139. } else {
  140. w.Header().Set("Content-Type", "application/json")
  141. //get the auth token
  142. bearerToken := r.Header.Get("Authorization")
  143. var tokenSplit = strings.Split(bearerToken, " ")
  144. //I put this in in case the user doesn't put in a token at all (in which case it's empty)
  145. //There's probably a smarter way of handling this.
  146. var authToken = "928rt238tghgwe@TY@$Y@#WQAEGB2FC#@HG#@$Hddd"
  147. if len(tokenSplit) > 1 {
  148. authToken = tokenSplit[1]
  149. } else {
  150. errorResponse = models.ErrorResponse{
  151. Code: http.StatusUnauthorized, Message: "W1R3: Missing Auth Token.",
  152. }
  153. returnErrorResponse(w, r, errorResponse)
  154. return
  155. }
  156. var isAuthorized = false
  157. var nodeID = ""
  158. username, networks, isadmin, errN := logic.VerifyUserToken(authToken)
  159. isnetadmin := isadmin
  160. if errN == nil && isadmin {
  161. nodeID = "mastermac"
  162. isAuthorized = true
  163. r.Header.Set("ismasterkey", "yes")
  164. }
  165. if !isadmin && params["network"] != "" {
  166. if logic.StringSliceContains(networks, params["network"]) {
  167. isnetadmin = true
  168. }
  169. }
  170. //The mastermac (login with masterkey from config) can do everything!! May be dangerous.
  171. if nodeID == "mastermac" {
  172. isAuthorized = true
  173. r.Header.Set("ismasterkey", "yes")
  174. //for everyone else, there's poor man's RBAC. The "cases" are defined in the routes in the handlers
  175. //So each route defines which access network should be allowed to access it
  176. } else {
  177. switch authNetwork {
  178. case "all":
  179. isAuthorized = true
  180. case "nodes":
  181. isAuthorized = (nodeID != "") || isnetadmin
  182. case "network":
  183. if isnetadmin {
  184. isAuthorized = true
  185. } else {
  186. node, err := logic.GetNodeByID(nodeID)
  187. if err != nil {
  188. errorResponse = models.ErrorResponse{
  189. Code: http.StatusUnauthorized, Message: "W1R3: Missing Auth Token.",
  190. }
  191. returnErrorResponse(w, r, errorResponse)
  192. return
  193. }
  194. isAuthorized = (node.Network == params["network"])
  195. }
  196. case "node":
  197. if isnetadmin {
  198. isAuthorized = true
  199. } else {
  200. isAuthorized = (nodeID == params["netid"])
  201. }
  202. case "user":
  203. isAuthorized = true
  204. default:
  205. isAuthorized = false
  206. }
  207. }
  208. if !isAuthorized {
  209. errorResponse = models.ErrorResponse{
  210. Code: http.StatusUnauthorized, Message: "W1R3: You are unauthorized to access this endpoint.",
  211. }
  212. returnErrorResponse(w, r, errorResponse)
  213. return
  214. } else {
  215. //If authorized, this function passes along it's request and output to the appropriate route function.
  216. if username == "" {
  217. username = "(user not found)"
  218. }
  219. r.Header.Set("user", username)
  220. next.ServeHTTP(w, r)
  221. }
  222. }
  223. }
  224. }
  225. //Gets all nodes associated with network, including pending nodes
  226. func getNetworkNodes(w http.ResponseWriter, r *http.Request) {
  227. w.Header().Set("Content-Type", "application/json")
  228. var nodes []models.Node
  229. var params = mux.Vars(r)
  230. networkName := params["network"]
  231. nodes, err := logic.GetNetworkNodes(networkName)
  232. if err != nil {
  233. returnErrorResponse(w, r, formatError(err, "internal"))
  234. return
  235. }
  236. //Returns all the nodes in JSON format
  237. logger.Log(2, r.Header.Get("user"), "fetched nodes on network", networkName)
  238. w.WriteHeader(http.StatusOK)
  239. json.NewEncoder(w).Encode(nodes)
  240. }
  241. //A separate function to get all nodes, not just nodes for a particular network.
  242. //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
  243. func getAllNodes(w http.ResponseWriter, r *http.Request) {
  244. w.Header().Set("Content-Type", "application/json")
  245. user, err := logic.GetUser(r.Header.Get("user"))
  246. if err != nil && r.Header.Get("ismasterkey") != "yes" {
  247. returnErrorResponse(w, r, formatError(err, "internal"))
  248. return
  249. }
  250. var nodes []models.Node
  251. if user.IsAdmin || r.Header.Get("ismasterkey") == "yes" {
  252. nodes, err = logic.GetAllNodes()
  253. if err != nil {
  254. returnErrorResponse(w, r, formatError(err, "internal"))
  255. return
  256. }
  257. } else {
  258. nodes, err = getUsersNodes(user)
  259. if err != nil {
  260. returnErrorResponse(w, r, formatError(err, "internal"))
  261. return
  262. }
  263. }
  264. //Return all the nodes in JSON format
  265. logger.Log(2, r.Header.Get("user"), "fetched nodes")
  266. w.WriteHeader(http.StatusOK)
  267. json.NewEncoder(w).Encode(nodes)
  268. }
  269. func getUsersNodes(user models.User) ([]models.Node, error) {
  270. var nodes []models.Node
  271. var err error
  272. for _, networkName := range user.Networks {
  273. tmpNodes, err := logic.GetNetworkNodes(networkName)
  274. if err != nil {
  275. continue
  276. }
  277. nodes = append(nodes, tmpNodes...)
  278. }
  279. return nodes, err
  280. }
  281. //Get an individual node. Nothin fancy here folks.
  282. func getNode(w http.ResponseWriter, r *http.Request) {
  283. // set header.
  284. w.Header().Set("Content-Type", "application/json")
  285. var params = mux.Vars(r)
  286. node, err := logic.GetNodeByID(params["nodeid"])
  287. if err != nil {
  288. returnErrorResponse(w, r, formatError(err, "internal"))
  289. return
  290. }
  291. logger.Log(2, r.Header.Get("user"), "fetched node", params["nodeid"])
  292. w.WriteHeader(http.StatusOK)
  293. json.NewEncoder(w).Encode(node)
  294. }
  295. //Get the time that a network of nodes was last modified.
  296. //TODO: This needs to be refactored
  297. //Potential way to do this: On UpdateNode, set a new field for "LastModified"
  298. //If we go with the existing way, we need to at least set network.NodesLastModified on UpdateNode
  299. func getLastModified(w http.ResponseWriter, r *http.Request) {
  300. // set header.
  301. w.Header().Set("Content-Type", "application/json")
  302. var params = mux.Vars(r)
  303. network, err := logic.GetNetwork(params["network"])
  304. if err != nil {
  305. returnErrorResponse(w, r, formatError(err, "internal"))
  306. return
  307. }
  308. logger.Log(2, r.Header.Get("user"), "called last modified")
  309. w.WriteHeader(http.StatusOK)
  310. json.NewEncoder(w).Encode(network.NodesLastModified)
  311. }
  312. func createNode(w http.ResponseWriter, r *http.Request) {
  313. w.Header().Set("Content-Type", "application/json")
  314. var params = mux.Vars(r)
  315. var errorResponse = models.ErrorResponse{
  316. Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
  317. }
  318. networkName := params["network"]
  319. networkexists, err := functions.NetworkExists(networkName)
  320. if err != nil {
  321. returnErrorResponse(w, r, formatError(err, "internal"))
  322. return
  323. } else if !networkexists {
  324. errorResponse = models.ErrorResponse{
  325. Code: http.StatusNotFound, Message: "W1R3: Network does not exist! ",
  326. }
  327. returnErrorResponse(w, r, errorResponse)
  328. return
  329. }
  330. var node = models.Node{}
  331. //get node from body of request
  332. err = json.NewDecoder(r.Body).Decode(&node)
  333. if err != nil {
  334. returnErrorResponse(w, r, formatError(err, "internal"))
  335. return
  336. }
  337. node.Network = networkName
  338. network, err := logic.GetNetworkByNode(&node)
  339. if err != nil {
  340. returnErrorResponse(w, r, formatError(err, "internal"))
  341. return
  342. }
  343. validKey := logic.IsKeyValid(networkName, node.AccessKey)
  344. if !validKey {
  345. //Check to see if network will allow manual sign up
  346. //may want to switch this up with the valid key check and avoid a DB call that way.
  347. if network.AllowManualSignUp == "yes" {
  348. node.IsPending = "yes"
  349. } else {
  350. errorResponse = models.ErrorResponse{
  351. Code: http.StatusUnauthorized, Message: "W1R3: Key invalid, or none provided.",
  352. }
  353. returnErrorResponse(w, r, errorResponse)
  354. return
  355. }
  356. }
  357. err = logic.CreateNode(&node)
  358. if err != nil {
  359. returnErrorResponse(w, r, formatError(err, "internal"))
  360. return
  361. }
  362. logger.Log(1, r.Header.Get("user"), "created new node", node.Name, "on network", node.Network)
  363. w.WriteHeader(http.StatusOK)
  364. json.NewEncoder(w).Encode(node)
  365. }
  366. //Takes node out of pending state
  367. //TODO: May want to use cordon/uncordon terminology instead of "ispending".
  368. func uncordonNode(w http.ResponseWriter, r *http.Request) {
  369. var params = mux.Vars(r)
  370. w.Header().Set("Content-Type", "application/json")
  371. node, err := logic.UncordonNode(params["nodeid"])
  372. if err != nil {
  373. returnErrorResponse(w, r, formatError(err, "internal"))
  374. return
  375. }
  376. go func() {
  377. if err := mq.NodeUpdate(&node); err != nil {
  378. logger.Log(1, "error publishing node update"+err.Error())
  379. }
  380. if err := mq.UpdatePeers(&node); err != nil {
  381. logger.Log(1, "error publishing peer update "+err.Error())
  382. return
  383. }
  384. }()
  385. logger.Log(1, r.Header.Get("user"), "uncordoned node", node.Name)
  386. w.WriteHeader(http.StatusOK)
  387. json.NewEncoder(w).Encode("SUCCESS")
  388. }
  389. func createEgressGateway(w http.ResponseWriter, r *http.Request) {
  390. var gateway models.EgressGatewayRequest
  391. var params = mux.Vars(r)
  392. w.Header().Set("Content-Type", "application/json")
  393. err := json.NewDecoder(r.Body).Decode(&gateway)
  394. if err != nil {
  395. returnErrorResponse(w, r, formatError(err, "internal"))
  396. return
  397. }
  398. gateway.NetID = params["network"]
  399. gateway.NodeID = params["nodeid"]
  400. node, err := logic.CreateEgressGateway(gateway)
  401. if err != nil {
  402. returnErrorResponse(w, r, formatError(err, "internal"))
  403. return
  404. }
  405. go func() {
  406. if err := mq.NodeUpdate(&node); err != nil {
  407. logger.Log(1, "error publishing node update"+err.Error())
  408. }
  409. if err := mq.UpdatePeers(&node); err != nil {
  410. logger.Log(1, "error publishing peer update "+err.Error())
  411. return
  412. }
  413. }()
  414. logger.Log(1, r.Header.Get("user"), "created egress gateway on node", gateway.NodeID, "on network", gateway.NetID)
  415. w.WriteHeader(http.StatusOK)
  416. json.NewEncoder(w).Encode(node)
  417. }
  418. func deleteEgressGateway(w http.ResponseWriter, r *http.Request) {
  419. w.Header().Set("Content-Type", "application/json")
  420. var params = mux.Vars(r)
  421. nodeid := params["nodeid"]
  422. netid := params["network"]
  423. node, err := logic.DeleteEgressGateway(netid, nodeid)
  424. if err != nil {
  425. returnErrorResponse(w, r, formatError(err, "internal"))
  426. return
  427. }
  428. go func() {
  429. if err := mq.NodeUpdate(&node); err != nil {
  430. logger.Log(1, "error publishing node update"+err.Error())
  431. }
  432. if err := mq.UpdatePeers(&node); err != nil {
  433. logger.Log(1, "error publishing peer update "+err.Error())
  434. return
  435. }
  436. }()
  437. logger.Log(1, r.Header.Get("user"), "deleted egress gateway", nodeid, "on network", netid)
  438. w.WriteHeader(http.StatusOK)
  439. json.NewEncoder(w).Encode(node)
  440. }
  441. // == INGRESS ==
  442. func createIngressGateway(w http.ResponseWriter, r *http.Request) {
  443. var params = mux.Vars(r)
  444. w.Header().Set("Content-Type", "application/json")
  445. nodeid := params["nodeid"]
  446. netid := params["network"]
  447. node, err := logic.CreateIngressGateway(netid, nodeid)
  448. if err != nil {
  449. returnErrorResponse(w, r, formatError(err, "internal"))
  450. return
  451. }
  452. go func() {
  453. if err := mq.NodeUpdate(&node); err != nil {
  454. logger.Log(1, "error publishing node update"+err.Error())
  455. }
  456. if err := mq.UpdatePeers(&node); err != nil {
  457. logger.Log(1, "error publishing peer update "+err.Error())
  458. return
  459. }
  460. }()
  461. logger.Log(1, r.Header.Get("user"), "created ingress gateway on node", nodeid, "on network", netid)
  462. w.WriteHeader(http.StatusOK)
  463. json.NewEncoder(w).Encode(node)
  464. }
  465. func deleteIngressGateway(w http.ResponseWriter, r *http.Request) {
  466. w.Header().Set("Content-Type", "application/json")
  467. var params = mux.Vars(r)
  468. nodeid := params["nodeid"]
  469. node, err := logic.DeleteIngressGateway(params["network"], nodeid)
  470. if err != nil {
  471. returnErrorResponse(w, r, formatError(err, "internal"))
  472. return
  473. }
  474. go func() {
  475. if err := mq.NodeUpdate(&node); err != nil {
  476. logger.Log(1, "error publishing node update"+err.Error())
  477. }
  478. if err := mq.UpdatePeers(&node); err != nil {
  479. logger.Log(1, "error publishing peer update "+err.Error())
  480. return
  481. }
  482. }()
  483. logger.Log(1, r.Header.Get("user"), "deleted ingress gateway", nodeid)
  484. w.WriteHeader(http.StatusOK)
  485. json.NewEncoder(w).Encode(node)
  486. }
  487. func updateNode(w http.ResponseWriter, r *http.Request) {
  488. w.Header().Set("Content-Type", "application/json")
  489. var params = mux.Vars(r)
  490. var node models.Node
  491. //start here
  492. node, err := logic.GetNodeByID(params["nodeid"])
  493. if err != nil {
  494. returnErrorResponse(w, r, formatError(err, "internal"))
  495. return
  496. }
  497. var newNode models.Node
  498. // we decode our body request params
  499. err = json.NewDecoder(r.Body).Decode(&newNode)
  500. if err != nil {
  501. returnErrorResponse(w, r, formatError(err, "badrequest"))
  502. return
  503. }
  504. newNode.PullChanges = "yes"
  505. relayupdate := false
  506. if node.IsRelay == "yes" && len(newNode.RelayAddrs) > 0 {
  507. if len(newNode.RelayAddrs) != len(node.RelayAddrs) {
  508. relayupdate = true
  509. } else {
  510. for i, addr := range newNode.RelayAddrs {
  511. if addr != node.RelayAddrs[i] {
  512. relayupdate = true
  513. }
  514. }
  515. }
  516. }
  517. if !servercfg.GetRce() {
  518. newNode.PostDown = node.PostDown
  519. newNode.PostUp = node.PostUp
  520. }
  521. err = logic.UpdateNode(&node, &newNode)
  522. if err != nil {
  523. returnErrorResponse(w, r, formatError(err, "internal"))
  524. return
  525. }
  526. if relayupdate {
  527. logic.UpdateRelay(node.Network, node.RelayAddrs, newNode.RelayAddrs)
  528. if err = logic.NetworkNodesUpdatePullChanges(node.Network); err != nil {
  529. logger.Log(1, "error setting relay updates:", err.Error())
  530. }
  531. }
  532. if servercfg.IsDNSMode() {
  533. err = logic.SetDNS()
  534. }
  535. if err != nil {
  536. returnErrorResponse(w, r, formatError(err, "internal"))
  537. return
  538. }
  539. logger.Log(1, r.Header.Get("user"), "updated node", node.MacAddress, "on network", node.Network)
  540. w.WriteHeader(http.StatusOK)
  541. json.NewEncoder(w).Encode(newNode)
  542. go func() {
  543. if err := mq.NodeUpdate(&newNode); err != nil {
  544. logger.Log(1, "error publishing node update"+err.Error())
  545. }
  546. if logic.ShouldPeersUpdate(&node, &newNode) {
  547. if err := mq.UpdatePeers(&newNode); err != nil {
  548. logger.Log(1, "error publishing peer update after node update"+err.Error())
  549. }
  550. }
  551. }()
  552. }
  553. func deleteNode(w http.ResponseWriter, r *http.Request) {
  554. // Set header
  555. w.Header().Set("Content-Type", "application/json")
  556. // get params
  557. var params = mux.Vars(r)
  558. var nodeid = params["nodeid"]
  559. var node, err = logic.GetNodeByID(nodeid)
  560. if err != nil {
  561. returnErrorResponse(w, r, formatError(err, "badrequest"))
  562. return
  563. }
  564. err = logic.DeleteNodeByID(&node, false)
  565. if err != nil {
  566. returnErrorResponse(w, r, formatError(err, "internal"))
  567. return
  568. }
  569. node.Action = models.NODE_DELETE
  570. go func() {
  571. if err := mq.NodeUpdate(&node); err != nil {
  572. logger.Log(1, "error publishing node delete "+err.Error())
  573. }
  574. }()
  575. logger.Log(1, r.Header.Get("user"), "Deleted node", nodeid, "from network", params["network"])
  576. returnSuccessResponse(w, r, nodeid+" deleted.")
  577. }