confirm.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package web
  2. import (
  3. "net/http"
  4. "net/url"
  5. "strings"
  6. "github.com/gin-contrib/sessions"
  7. "github.com/gin-gonic/gin"
  8. csrf "github.com/utrack/gin-csrf"
  9. )
  10. type QueueOp string
  11. const (
  12. OpDelete QueueOp = "delete"
  13. OpRedrive QueueOp = "redrive"
  14. OpInvalid QueueOp = "invalid"
  15. )
  16. // getOp extracts the operation from the unsafe form data, returning a safe value.
  17. func getOp(u *url.URL) QueueOp {
  18. q := u.Query()
  19. found := 0
  20. var res QueueOp
  21. for key := range q {
  22. switch op := QueueOp(strings.ToLower(key)); op {
  23. case OpDelete, OpRedrive:
  24. res = op
  25. found++
  26. default:
  27. continue
  28. }
  29. }
  30. if found != 1 {
  31. return OpInvalid
  32. }
  33. return res
  34. }
  35. func parseIDs(u *url.URL) []string {
  36. const prefix = "id-"
  37. q := u.Query()
  38. var ids []string
  39. for k, vs := range q {
  40. // Weed out bad keys, bad value lengths, and non-matching checkbox statuses.
  41. if pos := strings.Index(k, prefix); pos == -1 || len(vs) != 1 || vs[0] != "on" {
  42. continue
  43. }
  44. b, a, found := strings.Cut(k, prefix)
  45. if b == "" && found {
  46. ids = append(ids, a)
  47. }
  48. }
  49. return ids
  50. }
  51. type confirmData struct {
  52. question, description string
  53. confirm, cancel string
  54. redirect string // site-relative path
  55. }
  56. func makeConfirmHandler() gin.HandlerFunc {
  57. return func(c *gin.Context) {
  58. u := c.Request.URL
  59. op := getOp(u)
  60. var data confirmData
  61. switch op {
  62. case OpDelete:
  63. data = confirmDelete(c)
  64. case OpRedrive:
  65. data = confirmRedrive(c)
  66. default:
  67. data = confirmInvalid(c)
  68. }
  69. ids := parseIDs(u)
  70. sess := sessions.Default(c)
  71. flashes := sess.Flashes()
  72. token := csrf.GetToken(c)
  73. sess.Save()
  74. c.HTML(http.StatusOK, "confirm", gin.H{
  75. "cancel": "Cancel",
  76. "confirm": data.confirm,
  77. "csrf": token,
  78. "description": data.description,
  79. "flashes": flashes,
  80. "list": ids,
  81. "question": data.question,
  82. "redirect": data.redirect,
  83. })
  84. }
  85. }
  86. func confirmDelete(c *gin.Context) confirmData {
  87. qName := c.Param("name")
  88. cd := confirmData{
  89. cancel: "",
  90. confirm: "Delete",
  91. description: "These messages cannot be recovered after that step",
  92. question: "Do you confirm this deletion request ?",
  93. redirect: "/queue/" + qName,
  94. }
  95. if qName == "" {
  96. cd.redirect = "/"
  97. }
  98. return cd
  99. }
  100. func confirmRedrive(c *gin.Context) confirmData {
  101. cd := confirmData{}
  102. return cd
  103. }
  104. func confirmInvalid(c *gin.Context) confirmData {
  105. cd := confirmData{}
  106. return cd
  107. }