tags.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. package controller
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net/http"
  7. "net/url"
  8. "strings"
  9. "time"
  10. "github.com/gorilla/mux"
  11. "github.com/gravitl/netmaker/logger"
  12. "github.com/gravitl/netmaker/logic"
  13. "github.com/gravitl/netmaker/models"
  14. )
  15. func tagHandlers(r *mux.Router) {
  16. r.HandleFunc("/api/v1/tags", logic.SecurityCheck(true, http.HandlerFunc(getTags))).
  17. Methods(http.MethodGet)
  18. r.HandleFunc("/api/v1/tags", logic.SecurityCheck(true, http.HandlerFunc(createTag))).
  19. Methods(http.MethodPost)
  20. r.HandleFunc("/api/v1/tags", logic.SecurityCheck(true, http.HandlerFunc(updateTag))).
  21. Methods(http.MethodPut)
  22. r.HandleFunc("/api/v1/tags", logic.SecurityCheck(true, http.HandlerFunc(deleteTag))).
  23. Methods(http.MethodDelete)
  24. }
  25. // @Summary List Tags in a network
  26. // @Router /api/v1/tags [get]
  27. // @Tags TAG
  28. // @Accept json
  29. // @Success 200 {array} models.SuccessResponse
  30. // @Failure 500 {object} models.ErrorResponse
  31. func getTags(w http.ResponseWriter, r *http.Request) {
  32. netID, _ := url.QueryUnescape(r.URL.Query().Get("network"))
  33. if netID == "" {
  34. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("network id param is missing"), "badrequest"))
  35. return
  36. }
  37. // check if network exists
  38. _, err := logic.GetNetwork(netID)
  39. if err != nil {
  40. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  41. return
  42. }
  43. tags, err := logic.ListTagsWithNodes(models.NetworkID(netID))
  44. if err != nil {
  45. logger.Log(0, r.Header.Get("user"), "failed to get all network tag entries: ", err.Error())
  46. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  47. return
  48. }
  49. logic.SortTagEntrys(tags[:])
  50. logic.ReturnSuccessResponseWithJson(w, r, tags, "fetched all tags in the network "+netID)
  51. }
  52. // @Summary Create Tag
  53. // @Router /api/v1/tags [post]
  54. // @Tags TAG
  55. // @Accept json
  56. // @Success 200 {array} models.SuccessResponse
  57. // @Failure 500 {object} models.ErrorResponse
  58. func createTag(w http.ResponseWriter, r *http.Request) {
  59. var req models.CreateTagReq
  60. err := json.NewDecoder(r.Body).Decode(&req)
  61. if err != nil {
  62. logger.Log(0, "error decoding request body: ",
  63. err.Error())
  64. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  65. return
  66. }
  67. user, err := logic.GetUser(r.Header.Get("user"))
  68. if err != nil {
  69. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  70. return
  71. }
  72. // check if tag network exists
  73. _, err = logic.GetNetwork(req.Network.String())
  74. if err != nil {
  75. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("failed to get network details for "+req.Network.String()), "badrequest"))
  76. return
  77. }
  78. // check if tag exists
  79. tag := models.Tag{
  80. ID: models.TagID(fmt.Sprintf("%s.%s", req.Network, req.TagName)),
  81. TagName: req.TagName,
  82. Network: req.Network,
  83. CreatedBy: user.UserName,
  84. CreatedAt: time.Now(),
  85. }
  86. _, err = logic.GetTag(tag.ID)
  87. if err == nil {
  88. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("tag with id %s exists already", tag.TagName), "badrequest"))
  89. return
  90. }
  91. // validate name
  92. err = logic.CheckIDSyntax(tag.TagName)
  93. if err != nil {
  94. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  95. return
  96. }
  97. err = logic.InsertTag(tag)
  98. if err != nil {
  99. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  100. return
  101. }
  102. go func() {
  103. for _, node := range req.TaggedNodes {
  104. if node.IsStatic {
  105. extclient, err := logic.GetExtClient(node.StaticNode.ClientID, node.StaticNode.Network)
  106. if err == nil && extclient.RemoteAccessClientID == "" {
  107. if extclient.Tags == nil {
  108. extclient.Tags = make(map[models.TagID]struct{})
  109. }
  110. extclient.Tags[tag.ID] = struct{}{}
  111. logic.SaveExtClient(&extclient)
  112. }
  113. continue
  114. }
  115. node, err := logic.GetNodeByID(node.ID)
  116. if err != nil {
  117. continue
  118. }
  119. if node.Tags == nil {
  120. node.Tags = make(map[models.TagID]struct{})
  121. }
  122. node.Tags[tag.ID] = struct{}{}
  123. logic.UpsertNode(&node)
  124. }
  125. }()
  126. logic.ReturnSuccessResponseWithJson(w, r, req, "created tag successfully")
  127. }
  128. // @Summary Update Tag
  129. // @Router /api/v1/tags [put]
  130. // @Tags TAG
  131. // @Accept json
  132. // @Success 200 {array} models.SuccessResponse
  133. // @Failure 500 {object} models.ErrorResponse
  134. func updateTag(w http.ResponseWriter, r *http.Request) {
  135. var updateTag models.UpdateTagReq
  136. err := json.NewDecoder(r.Body).Decode(&updateTag)
  137. if err != nil {
  138. logger.Log(0, "error decoding request body: ",
  139. err.Error())
  140. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  141. return
  142. }
  143. tag, err := logic.GetTag(updateTag.ID)
  144. if err != nil {
  145. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  146. return
  147. }
  148. updateTag.NewName = strings.TrimSpace(updateTag.NewName)
  149. var newID models.TagID
  150. if updateTag.NewName != "" {
  151. // validate name
  152. err = logic.CheckIDSyntax(updateTag.NewName)
  153. if err != nil {
  154. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  155. return
  156. }
  157. newID = models.TagID(fmt.Sprintf("%s.%s", tag.Network, updateTag.NewName))
  158. tag.ID = newID
  159. tag.TagName = updateTag.NewName
  160. err = logic.InsertTag(tag)
  161. if err != nil {
  162. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  163. return
  164. }
  165. // delete old Tag entry
  166. logic.DeleteTag(updateTag.ID)
  167. }
  168. go logic.UpdateTag(updateTag, newID)
  169. logic.ReturnSuccessResponse(w, r, "updating tags")
  170. }
  171. // @Summary Delete Tag
  172. // @Router /api/v1/tags [delete]
  173. // @Tags TAG
  174. // @Accept json
  175. // @Success 200 {array} models.SuccessResponse
  176. // @Failure 500 {object} models.ErrorResponse
  177. func deleteTag(w http.ResponseWriter, r *http.Request) {
  178. tagID, _ := url.QueryUnescape(r.URL.Query().Get("tag_id"))
  179. if tagID == "" {
  180. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("role is required"), "badrequest"))
  181. return
  182. }
  183. err := logic.DeleteTag(models.TagID(tagID))
  184. if err != nil {
  185. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  186. return
  187. }
  188. logic.ReturnSuccessResponse(w, r, "deleted tag "+tagID)
  189. }