tags.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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. var res models.TagListRespNodes = models.TagListRespNodes{
  127. Tag: tag,
  128. UsedByCnt: len(req.TaggedNodes),
  129. TaggedNodes: req.TaggedNodes,
  130. }
  131. logic.ReturnSuccessResponseWithJson(w, r, res, "created tag successfully")
  132. }
  133. // @Summary Update Tag
  134. // @Router /api/v1/tags [put]
  135. // @Tags TAG
  136. // @Accept json
  137. // @Success 200 {array} models.SuccessResponse
  138. // @Failure 500 {object} models.ErrorResponse
  139. func updateTag(w http.ResponseWriter, r *http.Request) {
  140. var updateTag models.UpdateTagReq
  141. err := json.NewDecoder(r.Body).Decode(&updateTag)
  142. if err != nil {
  143. logger.Log(0, "error decoding request body: ",
  144. err.Error())
  145. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  146. return
  147. }
  148. tag, err := logic.GetTag(updateTag.ID)
  149. if err != nil {
  150. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  151. return
  152. }
  153. updateTag.NewName = strings.TrimSpace(updateTag.NewName)
  154. var newID models.TagID
  155. if updateTag.NewName != "" {
  156. // validate name
  157. err = logic.CheckIDSyntax(updateTag.NewName)
  158. if err != nil {
  159. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  160. return
  161. }
  162. newID = models.TagID(fmt.Sprintf("%s.%s", tag.Network, updateTag.NewName))
  163. tag.ID = newID
  164. tag.TagName = updateTag.NewName
  165. err = logic.InsertTag(tag)
  166. if err != nil {
  167. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  168. return
  169. }
  170. // delete old Tag entry
  171. logic.DeleteTag(updateTag.ID)
  172. }
  173. go logic.UpdateTag(updateTag, newID)
  174. var res models.TagListRespNodes = models.TagListRespNodes{
  175. Tag: tag,
  176. UsedByCnt: len(updateTag.TaggedNodes),
  177. TaggedNodes: updateTag.TaggedNodes,
  178. }
  179. logic.ReturnSuccessResponseWithJson(w, r, res, "updated tags")
  180. }
  181. // @Summary Delete Tag
  182. // @Router /api/v1/tags [delete]
  183. // @Tags TAG
  184. // @Accept json
  185. // @Success 200 {array} models.SuccessResponse
  186. // @Failure 500 {object} models.ErrorResponse
  187. func deleteTag(w http.ResponseWriter, r *http.Request) {
  188. tagID, _ := url.QueryUnescape(r.URL.Query().Get("tag_id"))
  189. if tagID == "" {
  190. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("role is required"), "badrequest"))
  191. return
  192. }
  193. err := logic.DeleteTag(models.TagID(tagID))
  194. if err != nil {
  195. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  196. return
  197. }
  198. logic.ReturnSuccessResponse(w, r, "deleted tag "+tagID)
  199. }