handlers.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Copyright (c) [2022] [巴拉迪维 BaratSemet]
  2. // [ohUrlShortener] is licensed under Mulan PSL v2.
  3. // You can use this software according to the terms and conditions of the Mulan PSL v2.
  4. // You may obtain a copy of Mulan PSL v2 at:
  5. // http://license.coscl.org.cn/MulanPSL2
  6. // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
  7. // See the Mulan PSL v2 for more details.
  8. package controller
  9. import (
  10. "fmt"
  11. "log"
  12. "net/http"
  13. "strconv"
  14. "strings"
  15. "ohurlshortener/core"
  16. "ohurlshortener/service"
  17. "ohurlshortener/storage"
  18. "ohurlshortener/utils"
  19. "github.com/gin-gonic/gin"
  20. )
  21. const (
  22. authorizationHeaderKey = "Authorization"
  23. authorizationTypeBearer = "Bearer"
  24. )
  25. // APIAuthHandler Authorization for /api
  26. func APIAuthHandler() gin.HandlerFunc {
  27. return func(ctx *gin.Context) {
  28. authHeader := ctx.GetHeader(authorizationHeaderKey)
  29. if utils.EmptyString(authHeader) {
  30. ctx.AbortWithStatusJSON(http.StatusUnauthorized, core.ResultJsonUnauthorized("Authorization Header is empty"))
  31. return
  32. }
  33. fields := strings.Fields(authHeader)
  34. if len(fields) < 2 {
  35. ctx.AbortWithStatusJSON(http.StatusUnauthorized, core.ResultJsonUnauthorized("Invalid Authorization Header"))
  36. return
  37. }
  38. if fields[0] != authorizationTypeBearer {
  39. ctx.AbortWithStatusJSON(http.StatusUnauthorized, core.ResultJsonUnauthorized("Unsupported Authorization Type"))
  40. return
  41. }
  42. token := fields[1]
  43. res, err := validateToken(token)
  44. if err != nil {
  45. ctx.AbortWithStatusJSON(http.StatusInternalServerError, core.ResultJsonError("Internal error"))
  46. return
  47. }
  48. if !res {
  49. ctx.AbortWithStatusJSON(http.StatusUnauthorized, core.ResultJsonUnauthorized("Authorization failed"))
  50. return
  51. }
  52. ctx.Next()
  53. }
  54. }
  55. // AdminCookieValue Generate cookie value for admin user
  56. func AdminCookieValue(user core.User) (string, error) {
  57. var result string
  58. data, err := utils.Sha256Of(user.Account + "a=" + user.Password + "=e" + strconv.Itoa(user.ID))
  59. if err != nil {
  60. log.Println(err)
  61. return result, err
  62. }
  63. return utils.Base58Encode(data), nil
  64. }
  65. // AdminAuthHandler Authorization for /admin
  66. func AdminAuthHandler() gin.HandlerFunc {
  67. return func(c *gin.Context) {
  68. user, err := c.Cookie("ohUrlShortenerAdmin")
  69. if err != nil {
  70. c.Redirect(http.StatusFound, "/login")
  71. c.Next()
  72. }
  73. cookie, err := c.Cookie("ohUrlShortenerCookie")
  74. if err != nil {
  75. c.Redirect(http.StatusFound, "/login")
  76. c.Next()
  77. return
  78. }
  79. if len(user) <= 0 || len(cookie) <= 0 {
  80. c.Redirect(http.StatusFound, "/login")
  81. c.Next()
  82. return
  83. }
  84. found, err := service.GetUserByAccountFromRedis(user)
  85. if err != nil {
  86. c.Redirect(http.StatusFound, "/login")
  87. c.Next()
  88. return
  89. }
  90. if found.IsEmpty() {
  91. c.Redirect(http.StatusFound, "/login")
  92. c.Next()
  93. return
  94. }
  95. cValue, err := AdminCookieValue(found)
  96. if err != nil {
  97. c.Redirect(http.StatusFound, "/login")
  98. c.Next()
  99. return
  100. }
  101. if !strings.EqualFold(cValue, cookie) {
  102. c.Redirect(http.StatusFound, "/login")
  103. c.Next()
  104. return
  105. }
  106. c.Set("current_account", found.Account)
  107. c.Next()
  108. } // end of func
  109. }
  110. // WebLogFormatHandler Customized log format for web
  111. func WebLogFormatHandler(server string) gin.HandlerFunc {
  112. return gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
  113. if !strings.HasPrefix(param.Path, "/assets") {
  114. return fmt.Sprintf("[%s | %s] %s %s %d %s \t%s %s %s \n",
  115. server,
  116. param.TimeStamp.Format("2006/01/02 15:04:05"),
  117. param.Method,
  118. param.Path,
  119. param.StatusCode,
  120. param.Latency,
  121. param.ClientIP,
  122. param.Request.UserAgent(),
  123. param.ErrorMessage,
  124. )
  125. } // end of if
  126. return ""
  127. }) // end of formatter
  128. } // end of func
  129. func validateToken(token string) (bool, error) {
  130. users, err := storage.FindAllUsers()
  131. if err != nil {
  132. return false, err
  133. }
  134. for _, u := range users {
  135. if u.Password == token {
  136. return true, nil
  137. }
  138. }
  139. return false, nil
  140. }