| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- // Copyright (c) [2022] [巴拉迪维 BaratSemet]
- // [ohUrlShortener] is licensed under Mulan PSL v2.
- // You can use this software according to the terms and conditions of the Mulan PSL v2.
- // You may obtain a copy of Mulan PSL v2 at:
- // http://license.coscl.org.cn/MulanPSL2
- // 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.
- // See the Mulan PSL v2 for more details.
- package controller
- import (
- "fmt"
- "net/http"
- "strconv"
- "strings"
- "time"
- "ohurlshortener/core"
- "ohurlshortener/service"
- "ohurlshortener/utils"
- "ohurlshortener/utils/export"
- "github.com/dchest/captcha"
- "github.com/gin-gonic/gin"
- )
- const (
- DefaultPageNum = 1
- DefaultPageSize = 20
- )
- // LoginPage 登录页面
- func LoginPage(c *gin.Context) {
- c.HTML(http.StatusOK, "login.html", gin.H{
- "title": "登录 - ohUrlShortener",
- })
- }
- // Users Page
- func UsersPage(c *gin.Context) {
- strPage := c.DefaultQuery("page", strconv.Itoa(DefaultPageNum))
- strSize := c.DefaultQuery("size", strconv.Itoa(DefaultPageSize))
- page, err := strconv.Atoi(strPage)
- if err != nil {
- page = DefaultPageNum
- }
- size, err := strconv.Atoi(strSize)
- if err != nil {
- size = DefaultPageSize
- }
- found, err := service.GetPagedUsers(page, size)
- c.HTML(http.StatusOK, "users.html", gin.H{
- "title": "用户管理 - ohUrlShortener",
- "current_url": c.Request.URL.Path,
- "users": found,
- "error": err,
- "page": page,
- "size": size,
- "first_page": page == 1,
- "last_page": len(found) < size,
- })
- }
- // DoLogin 登录
- func DoLogin(c *gin.Context) {
- account := c.PostForm("account")
- password := c.PostForm("password")
- captchaText := c.PostForm("captcha-text")
- captchaId := c.PostForm("captcha-id")
- if utils.EmptyString(account) || utils.EmptyString(password) || len(account) < 5 || len(password) < 8 {
- c.HTML(http.StatusOK, "login.html", gin.H{
- "title": "错误 - ohUrlShortener",
- "error": "用户名或密码格式错误!",
- })
- return
- }
- if utils.EmptyString(captchaText) || utils.EmptyString(captchaId) || len(captchaText) < 6 {
- c.HTML(http.StatusOK, "login.html", gin.H{
- "title": "错误 - ohUrlShortener",
- "error": "验证码格式错误!",
- })
- return
- }
- // 验证码有效性验证
- if !captcha.VerifyString(captchaId, captchaText) {
- c.HTML(http.StatusOK, "login.html", gin.H{
- "title": "错误 - ohUrlShortener",
- "error": "验证码错误,请刷新页面再重新尝试!",
- })
- return
- }
- // 用户名密码有效性验证
- loginUser, err := service.Login(account, password)
- if err != nil || loginUser.IsEmpty() {
- c.HTML(http.StatusOK, "login.html", gin.H{
- "title": "错误 - ohUrlShortener",
- "error": err.Error(),
- })
- return
- }
- // Write Cookie to browser
- cValue, err := AdminCookieValue(loginUser)
- if err != nil {
- c.HTML(http.StatusOK, "login.html", gin.H{
- "title": "错误 - ohUrlShortener",
- "error": "内部错误,请联系管理员",
- })
- return
- }
- c.SetCookie("ohUrlShortenerAdmin", loginUser.Account, 3600, "/", "", false, true)
- c.SetCookie("ohUrlShortenerCookie", cValue, 3600, "/", "", false, true)
- c.Redirect(http.StatusFound, "/admin/dashboard")
- }
- // DoLogout 登出
- func DoLogout(c *gin.Context) {
- c.SetCookie("ohUrlShortenerAdmin", "", -1, "/", "", false, true)
- c.SetCookie("ohUrlShortenerCookie", "", -1, "/", "", false, true)
- c.Redirect(http.StatusFound, "/login")
- }
- // ServeCaptchaImage 生成验证码
- func ServeCaptchaImage(c *gin.Context) {
- captcha.Server(200, 45).ServeHTTP(c.Writer, c.Request)
- }
- // RequestCaptchaImage 请求验证码
- func RequestCaptchaImage(c *gin.Context) {
- imageId := captcha.New()
- c.JSON(http.StatusOK, core.ResultJsonSuccessWithData(imageId))
- }
- // ChangeState 修改状态
- func ChangeState(c *gin.Context) {
- destUrl := c.PostForm("dest_url")
- enable := c.PostForm("enable")
- if utils.EmptyString(destUrl) {
- c.JSON(http.StatusBadRequest, core.ResultJsonError("目标链接不存在!"))
- return
- }
- destEnable, err := strconv.ParseBool(enable)
- if err != nil {
- c.JSON(http.StatusBadRequest, core.ResultJsonError("参数不合法!"))
- return
- }
- result, er := service.ChangeState(destUrl, destEnable)
- if er != nil {
- c.JSON(http.StatusInternalServerError, core.ResultJsonError(er.Error()))
- return
- }
- c.JSON(http.StatusOK, core.ResultJsonSuccessWithData(result))
- }
- // DeleteShortUrl 删除短链接
- func DeleteShortUrl(c *gin.Context) {
- url := c.PostForm("short_url")
- if utils.EmptyString(strings.TrimSpace(url)) {
- c.JSON(http.StatusBadRequest, core.ResultJsonError("目标链接不存在!"))
- return
- }
- err := service.DeleteUrlAndAccessLogs(url)
- if err != nil {
- c.JSON(http.StatusInternalServerError, core.ResultJsonError(err.Error()))
- return
- }
- c.JSON(http.StatusOK, core.ResultJsonSuccess())
- }
- // GenerateShortUrl 生成短链接
- func GenerateShortUrl(c *gin.Context) {
- destUrl := c.PostForm("dest_url")
- memo := c.PostForm("memo")
- strOpenType := c.PostForm("open_type")
- openType, err := strconv.Atoi(strOpenType)
- if err != nil {
- openType = int(core.OpenInAll)
- }
- if utils.EmptyString(destUrl) {
- c.JSON(http.StatusBadRequest, core.ResultJsonError("目标链接不能为空!"))
- return
- }
- result, err := service.GenerateShortUrl(destUrl, memo, openType)
- if err != nil {
- c.JSON(http.StatusInternalServerError, core.ResultJsonError(err.Error()))
- return
- }
- json := map[string]string{
- "short_url": fmt.Sprintf("%s%s", utils.AppConfig.UrlPrefix, result),
- }
- c.JSON(http.StatusOK, core.ResultJsonSuccessWithData(json))
- }
- // StatsPage 统计页面
- func StatsPage(c *gin.Context) {
- url := c.DefaultQuery("url", "")
- strPage := c.DefaultQuery("page", strconv.Itoa(DefaultPageNum))
- strSize := c.DefaultQuery("size", strconv.Itoa(DefaultPageSize))
- page, err := strconv.Atoi(strPage)
- if err != nil {
- page = DefaultPageNum
- }
- size, err := strconv.Atoi(strSize)
- if err != nil {
- size = DefaultPageSize
- }
- urls, err := service.GetPagedUrlIpCountStats(strings.TrimSpace(url), page, size)
- c.HTML(http.StatusOK, "stats.html", gin.H{
- "title": "数据统计 - ohUrlShortener",
- "current_url": c.Request.URL.Path,
- "error": err,
- "shortUrls": urls,
- "page": page,
- "size": size,
- "prefix": utils.AppConfig.UrlPrefix,
- "first_page": page == 1,
- "last_page": len(urls) < size,
- "url": strings.TrimSpace(url),
- })
- }
- // SearchStatsPage 查询统计页面
- func SearchStatsPage(c *gin.Context) {
- url := c.DefaultQuery("url", "")
- strPage := c.DefaultQuery("page", strconv.Itoa(DefaultPageNum))
- strSize := c.DefaultQuery("size", strconv.Itoa(DefaultPageSize))
- page, err := strconv.Atoi(strPage)
- if err != nil {
- page = DefaultPageNum
- }
- size, err := strconv.Atoi(strSize)
- if err != nil {
- size = DefaultPageSize
- }
- urls, err := service.GetPagedUrlIpCountStats(strings.TrimSpace(url), page, size)
- c.HTML(http.StatusOK, "search_stats.html", gin.H{
- "title": "查询统计 - ohUrlShortener",
- "current_url": c.Request.URL.Path,
- "error": err,
- "shortUrls": urls,
- "page": page,
- "size": size,
- "prefix": utils.AppConfig.UrlPrefix,
- "first_page": page == 1,
- "last_page": len(urls) < size,
- "url": strings.TrimSpace(url),
- })
- }
- // UrlsPage 短链接列表页面
- func UrlsPage(c *gin.Context) {
- url := c.DefaultQuery("url", "")
- strPage := c.DefaultQuery("page", strconv.Itoa(DefaultPageNum))
- strSize := c.DefaultQuery("size", strconv.Itoa(DefaultPageSize))
- page, err := strconv.Atoi(strPage)
- if err != nil {
- page = DefaultPageNum
- }
- size, err := strconv.Atoi(strSize)
- if err != nil {
- size = DefaultPageSize
- }
- urls, err := service.GetPagesShortUrls(strings.TrimSpace(url), page, size)
- c.HTML(http.StatusOK, "urls.html", gin.H{
- "title": "短链接列表 - ohUrlShortener",
- "current_url": c.Request.URL.Path,
- "error": err,
- "shortUrls": urls,
- "page": page,
- "size": size,
- "prefix": utils.AppConfig.UrlPrefix,
- "first_page": page == 1,
- "last_page": len(urls) < size,
- "url": strings.TrimSpace(url),
- })
- }
- // AccessLogsPage 访问日志页面
- func AccessLogsPage(c *gin.Context) {
- url := c.DefaultQuery("url", "")
- strPage := c.DefaultQuery("page", strconv.Itoa(DefaultPageNum))
- strSize := c.DefaultQuery("size", strconv.Itoa(DefaultPageSize))
- start := c.DefaultQuery("start", "")
- end := c.DefaultQuery("end", "")
- page, err := strconv.Atoi(strPage)
- if err != nil {
- page = DefaultPageNum
- }
- size, err := strconv.Atoi(strSize)
- if err != nil {
- size = DefaultPageSize
- }
- totalCount, distinctIpCount, err := service.GetAccessLogsCount(strings.TrimSpace(url), start, end)
- logs, err := service.GetPagedAccessLogs(strings.TrimSpace(url), start, end, page, size)
- c.HTML(http.StatusOK, "access_logs.html", gin.H{
- "title": "访问日志查询 - ohUrlShortener",
- "current_url": c.Request.URL.Path,
- "error": err,
- "logs": logs,
- "page": page,
- "size": size,
- "prefix": utils.AppConfig.UrlPrefix,
- "first_page": page == 1,
- "last_page": len(logs) < size,
- "url": strings.TrimSpace(url),
- "total_count": totalCount,
- "unique_ip_count": distinctIpCount,
- "start_date": start,
- "end_date": end,
- })
- }
- // AccessLogsExport 导出访问日志
- func AccessLogsExport(c *gin.Context) {
- url := c.PostForm("url")
- logs, err := service.GetAllAccessLogs(strings.TrimSpace(url))
- if err != nil {
- c.HTML(http.StatusOK, "access_logs.html", gin.H{
- "title": "访问日志查询 - ohUrlShortener",
- "current_url": c.Request.URL.Path,
- "prefix": utils.AppConfig.UrlPrefix,
- "url": strings.TrimSpace(url),
- "error": err,
- })
- return
- }
- fileContent, err := export.AccessLogToExcel(logs)
- if err != nil {
- c.HTML(http.StatusOK, "access_logs.html", gin.H{
- "title": "访问日志查询 - ohUrlShortener",
- "current_url": c.Request.URL.Path,
- "prefix": utils.AppConfig.UrlPrefix,
- "url": strings.TrimSpace(url),
- "error": err,
- })
- return
- }
- attachmentName := "访问日志" + time.Now().Format("2006-01-02 150405") + ".xlsx"
- fileContentDisposition := "attachment;filename=\"" + attachmentName + "\""
- c.Header("Content-Disposition", fileContentDisposition)
- c.Data(http.StatusOK, "pplication/octet-stream", fileContent)
- }
- // DashboardPage 仪表盘页面
- func DashboardPage(c *gin.Context) {
- count, stats, err := service.GetSumOfUrlStats()
- if err != nil {
- c.HTML(http.StatusOK, "dashboard.html", gin.H{
- "title": "仪表盘 - ohUrlShortener",
- "current_url": c.Request.URL.Path,
- "error": err,
- })
- return
- }
- top25, er := service.GetTop25Url()
- if er != nil {
- c.HTML(http.StatusOK, "dashboard.html", gin.H{
- "title": "仪表盘 - ohUrlShortener",
- "current_url": c.Request.URL.Path,
- "error": er,
- })
- return
- }
- c.HTML(http.StatusOK, "dashboard.html", gin.H{
- "title": "仪表盘 - ohUrlShortener",
- "current_url": c.Request.URL.Path,
- "error": err,
- "total_count": count,
- "prefix": utils.AppConfig.UrlPrefix,
- "stats": stats,
- "top25": top25,
- })
- }
|