admin_controller.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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. "net/http"
  12. "ohurlshortener/core"
  13. "ohurlshortener/service"
  14. "ohurlshortener/utils"
  15. "strconv"
  16. "strings"
  17. "github.com/dchest/captcha"
  18. "github.com/gin-gonic/gin"
  19. )
  20. const (
  21. DEFAULT_PAGE_NUM = 1
  22. DEFAULT_PAGE_SIZE = 20
  23. )
  24. func LoginPage(c *gin.Context) {
  25. c.HTML(http.StatusOK, "login.html", gin.H{
  26. "title": "登录 - ohUrlShortener",
  27. })
  28. }
  29. func DoLogin(c *gin.Context) {
  30. account := c.PostForm("account")
  31. password := c.PostForm("password")
  32. captchaText := c.PostForm("captcha-text")
  33. captchaId := c.PostForm("captcha-id")
  34. if utils.EemptyString(account) || utils.EemptyString(password) || len(account) < 5 || len(password) < 8 {
  35. c.HTML(http.StatusOK, "login.html", gin.H{
  36. "title": "错误 - ohUrlShortener",
  37. "error": "用户名或密码格式错误!",
  38. })
  39. return
  40. }
  41. if utils.EemptyString(captchaText) || utils.EemptyString(captchaId) || len(captchaText) < 6 {
  42. c.HTML(http.StatusOK, "login.html", gin.H{
  43. "title": "错误 - ohUrlShortener",
  44. "error": "验证码格式错误!",
  45. })
  46. return
  47. }
  48. //验证码有效性验证
  49. if !captcha.VerifyString(captchaId, captchaText) {
  50. c.HTML(http.StatusOK, "login.html", gin.H{
  51. "title": "错误 - ohUrlShortener",
  52. "error": "验证码错误,请刷新页面再重新尝试!",
  53. })
  54. return
  55. }
  56. //用户名密码有效性验证
  57. loginUser, err := service.Login(account, password)
  58. if err != nil || loginUser.IsEmpty() {
  59. c.HTML(http.StatusOK, "login.html", gin.H{
  60. "title": "错误 - ohUrlShortener",
  61. "error": err.Error(),
  62. })
  63. return
  64. }
  65. //Write Cookie to browser
  66. cValue, err := AdminCookieValue(loginUser)
  67. if err != nil {
  68. c.HTML(http.StatusOK, "login.html", gin.H{
  69. "title": "错误 - ohUrlShortener",
  70. "error": "内部错误,请联系管理员",
  71. })
  72. return
  73. }
  74. c.SetCookie("ohUrlShortenerAdmin", loginUser.Account, 3600, "/", "", true, true)
  75. c.SetCookie("ohUrlShortenerCookie", cValue, 3600, "/", "", true, true)
  76. c.Redirect(http.StatusFound, "/admin/dashboard")
  77. }
  78. func DoLogout(c *gin.Context) {
  79. c.SetCookie("ohUrlShortenerAdmin", "", -1, "/", "", true, true)
  80. c.SetCookie("ohUrlShortenerCookie", "", -1, "/", "", true, true)
  81. c.Redirect(http.StatusFound, "/login")
  82. }
  83. func ServeCaptchaImage(c *gin.Context) {
  84. captcha.Server(200, 45).ServeHTTP(c.Writer, c.Request)
  85. }
  86. func RequestCaptchaImage(c *gin.Context) {
  87. imageId := captcha.New()
  88. c.JSON(http.StatusOK, core.ResultJsonSuccessWithData(imageId))
  89. }
  90. func ChangeState(c *gin.Context) {
  91. destUrl := c.PostForm("dest_url")
  92. enable := c.PostForm("enable")
  93. if utils.EemptyString(destUrl) {
  94. c.JSON(http.StatusBadRequest, core.ResultJsonError("目标链接不存在!"))
  95. return
  96. }
  97. destEnable, err := strconv.ParseBool(enable)
  98. if err != nil {
  99. c.JSON(http.StatusBadRequest, core.ResultJsonError("参数不合法!"))
  100. return
  101. }
  102. result, er := service.ChangeState(destUrl, destEnable)
  103. if er != nil {
  104. c.JSON(http.StatusInternalServerError, core.ResultJsonError(er.Error()))
  105. return
  106. }
  107. c.JSON(http.StatusOK, core.ResultJsonSuccessWithData(result))
  108. }
  109. func GenerateShortUrl(c *gin.Context) {
  110. destUrl := c.PostForm("dest_url")
  111. memo := c.PostForm("memo")
  112. if utils.EemptyString(destUrl) {
  113. c.JSON(http.StatusBadRequest, core.ResultJsonError("目标链接不能为空!"))
  114. return
  115. }
  116. result, err := service.GenerateShortUrl(destUrl, memo)
  117. if err != nil {
  118. c.JSON(http.StatusInternalServerError, core.ResultJsonError(err.Error()))
  119. return
  120. }
  121. json := map[string]string{
  122. "short_url": fmt.Sprintf("%s%s", utils.AppConfig.UrlPrefix, result),
  123. }
  124. c.JSON(http.StatusOK, core.ResultJsonSuccessWithData(json))
  125. }
  126. func StatsPage(c *gin.Context) {
  127. url := c.DefaultQuery("url", "")
  128. strPage := c.DefaultQuery("page", strconv.Itoa(DEFAULT_PAGE_NUM))
  129. strSize := c.DefaultQuery("size", strconv.Itoa(DEFAULT_PAGE_SIZE))
  130. page, err := strconv.Atoi(strPage)
  131. if err != nil {
  132. page = DEFAULT_PAGE_NUM
  133. }
  134. size, err := strconv.Atoi(strSize)
  135. if err != nil {
  136. size = DEFAULT_PAGE_SIZE
  137. }
  138. urls, err := service.GetPagedUrlIpCountStats(strings.TrimSpace(url), page, size)
  139. c.HTML(http.StatusOK, "stats.html", gin.H{
  140. "title": "数据统计 - ohUrlShortener",
  141. "current_url": c.Request.URL.Path,
  142. "error": err,
  143. "shortUrls": urls,
  144. "page": page,
  145. "size": size,
  146. "prefix": utils.AppConfig.UrlPrefix,
  147. "first_page": page == 1,
  148. "last_page": len(urls) < size,
  149. "url": strings.TrimSpace(url),
  150. })
  151. }
  152. func UrlsPage(c *gin.Context) {
  153. url := c.DefaultQuery("url", "")
  154. strPage := c.DefaultQuery("page", strconv.Itoa(DEFAULT_PAGE_NUM))
  155. strSize := c.DefaultQuery("size", strconv.Itoa(DEFAULT_PAGE_SIZE))
  156. page, err := strconv.Atoi(strPage)
  157. if err != nil {
  158. page = DEFAULT_PAGE_NUM
  159. }
  160. size, err := strconv.Atoi(strSize)
  161. if err != nil {
  162. size = DEFAULT_PAGE_SIZE
  163. }
  164. urls, err := service.GetPagesShortUrls(strings.TrimSpace(url), page, size)
  165. c.HTML(http.StatusOK, "urls.html", gin.H{
  166. "title": "短链接列表 - ohUrlShortener",
  167. "current_url": c.Request.URL.Path,
  168. "error": err,
  169. "shortUrls": urls,
  170. "page": page,
  171. "size": size,
  172. "prefix": utils.AppConfig.UrlPrefix,
  173. "first_page": page == 1,
  174. "last_page": len(urls) < size,
  175. "url": strings.TrimSpace(url),
  176. })
  177. }
  178. func AccessLogsPage(c *gin.Context) {
  179. url := c.DefaultQuery("url", "")
  180. strPage := c.DefaultQuery("page", strconv.Itoa(DEFAULT_PAGE_NUM))
  181. strSize := c.DefaultQuery("size", strconv.Itoa(DEFAULT_PAGE_SIZE))
  182. page, err := strconv.Atoi(strPage)
  183. if err != nil {
  184. page = DEFAULT_PAGE_NUM
  185. }
  186. size, err := strconv.Atoi(strSize)
  187. if err != nil {
  188. size = DEFAULT_PAGE_SIZE
  189. }
  190. logs, err := service.GetPagedAccessLogs(strings.TrimSpace(url), page, size)
  191. c.HTML(http.StatusOK, "access_logs.html", gin.H{
  192. "title": "访问日志查询 - ohUrlShortener",
  193. "current_url": c.Request.URL.Path,
  194. "error": err,
  195. "logs": logs,
  196. "page": page,
  197. "size": size,
  198. "prefix": utils.AppConfig.UrlPrefix,
  199. "first_page": page == 1,
  200. "last_page": len(logs) < size,
  201. "url": strings.TrimSpace(url),
  202. })
  203. }
  204. func DashbaordPage(c *gin.Context) {
  205. count, stats, err := service.GetSumOfUrlStats()
  206. if err != nil {
  207. c.HTML(http.StatusOK, "dashboard.html", gin.H{
  208. "title": "仪表盘 - ohUrlShortener",
  209. "current_url": c.Request.URL.Path,
  210. "error": err,
  211. })
  212. return
  213. }
  214. top25, er := service.GetTop25Url()
  215. if er != nil {
  216. c.HTML(http.StatusOK, "dashboard.html", gin.H{
  217. "title": "仪表盘 - ohUrlShortener",
  218. "current_url": c.Request.URL.Path,
  219. "error": er,
  220. })
  221. return
  222. }
  223. c.HTML(http.StatusOK, "dashboard.html", gin.H{
  224. "title": "仪表盘 - ohUrlShortener",
  225. "current_url": c.Request.URL.Path,
  226. "error": err,
  227. "total_count": count,
  228. "prefix": utils.AppConfig.UrlPrefix,
  229. "stats": stats,
  230. "top25": top25,
  231. })
  232. }