From cf4b04e0473ac339d0ab11214f6408f0fefad73e Mon Sep 17 00:00:00 2001 From: RockYang Date: Fri, 29 Dec 2023 17:21:29 +0800 Subject: [PATCH] feat: add authorization for local function call --- api/handler/function_handler.go | 46 +++++++++++++++++++++++++++++++ web/src/assets/css/image-mj.css | 10 +++++++ web/src/assets/css/image-sd.css | 10 +++++++ web/src/assets/css/task-list.styl | 15 ++++++++++ 4 files changed, 81 insertions(+) diff --git a/api/handler/function_handler.go b/api/handler/function_handler.go index 4bcebf8b..a3bf3fec 100644 --- a/api/handler/function_handler.go +++ b/api/handler/function_handler.go @@ -7,11 +7,14 @@ import ( "chatplus/store/model" "chatplus/utils" "chatplus/utils/resp" + "errors" "fmt" "github.com/gin-gonic/gin" + "github.com/golang-jwt/jwt/v5" "github.com/imroc/req/v3" "gorm.io/gorm" "strings" + "time" ) type FunctionHandler struct { @@ -50,8 +53,41 @@ type dataItem struct { Remark string `json:"remark"` } +// check authorization +func (h *FunctionHandler) checkAuth(c *gin.Context) error { + tokenString := c.GetHeader(types.UserAuthHeader) + token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { + if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { + return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) + } + + return []byte(h.App.Config.Session.SecretKey), nil + }) + + if err != nil { + return fmt.Errorf("error with parse auth token: %v", err) + } + + claims, ok := token.Claims.(jwt.MapClaims) + if !ok || !token.Valid { + return errors.New("token is invalid") + } + + expr := utils.IntValue(utils.InterfaceToString(claims["expired"]), 0) + if expr > 0 && int64(expr) < time.Now().Unix() { + return errors.New("token is expired") + } + + return nil +} + // WeiBo 微博热搜 func (h *FunctionHandler) WeiBo(c *gin.Context) { + if err := h.checkAuth(c); err != nil { + resp.ERROR(c, err.Error()) + return + } + if h.config.Token == "" { resp.ERROR(c, "无效的 API Token") return @@ -83,6 +119,11 @@ func (h *FunctionHandler) WeiBo(c *gin.Context) { // ZaoBao 今日早报 func (h *FunctionHandler) ZaoBao(c *gin.Context) { + if err := h.checkAuth(c); err != nil { + resp.ERROR(c, err.Error()) + return + } + if h.config.Token == "" { resp.ERROR(c, "无效的 API Token") return @@ -139,6 +180,11 @@ type ErrRes struct { // Dall3 DallE3 AI 绘图 func (h *FunctionHandler) Dall3(c *gin.Context) { + if err := h.checkAuth(c); err != nil { + resp.ERROR(c, err.Error()) + return + } + var params map[string]interface{} if err := c.ShouldBindJSON(¶ms); err != nil { resp.ERROR(c, types.InvalidArgs) diff --git a/web/src/assets/css/image-mj.css b/web/src/assets/css/image-mj.css index d421a77e..44f552bc 100644 --- a/web/src/assets/css/image-mj.css +++ b/web/src/assets/css/image-mj.css @@ -299,6 +299,7 @@ overflow: hidden; border-radius: 6px; transition: all 0.3s ease; /* 添加过渡效果 */ + position: relative; } .page-mj .inner .task-list-box .finish-job-list .job-item .opt .opt-line { margin: 6px 0; @@ -327,6 +328,15 @@ font-size: 20px; cursor: pointer; } +.page-mj .inner .task-list-box .finish-job-list .job-item .remove { + display: none; + position: absolute; + right: 10px; + top: 10px; +} +.page-mj .inner .task-list-box .finish-job-list .job-item:hover .remove { + display: block; +} .page-mj .inner .task-list-box .finish-job-list .animate:hover { box-shadow: 0 0 10px rgba(71,255,241,0.6); /* 添加阴影效果 */ transform: translateY(-10px); /* 向上移动10像素 */ diff --git a/web/src/assets/css/image-sd.css b/web/src/assets/css/image-sd.css index 9bd76f37..edb58873 100644 --- a/web/src/assets/css/image-sd.css +++ b/web/src/assets/css/image-sd.css @@ -184,6 +184,7 @@ overflow: hidden; border-radius: 6px; transition: all 0.3s ease; /* 添加过渡效果 */ + position: relative; } .page-sd .inner .task-list-box .finish-job-list .job-item .opt .opt-line { margin: 6px 0; @@ -212,6 +213,15 @@ font-size: 20px; cursor: pointer; } +.page-sd .inner .task-list-box .finish-job-list .job-item .remove { + display: none; + position: absolute; + right: 10px; + top: 10px; +} +.page-sd .inner .task-list-box .finish-job-list .job-item:hover .remove { + display: block; +} .page-sd .inner .task-list-box .finish-job-list .animate:hover { box-shadow: 0 0 10px rgba(71,255,241,0.6); /* 添加阴影效果 */ transform: translateY(-10px); /* 向上移动10像素 */ diff --git a/web/src/assets/css/task-list.styl b/web/src/assets/css/task-list.styl index 92000098..61d1a111 100644 --- a/web/src/assets/css/task-list.styl +++ b/web/src/assets/css/task-list.styl @@ -148,6 +148,7 @@ overflow hidden border-radius 6px transition: all 0.3s ease; /* 添加过渡效果 */ + position relative .opt { .opt-line { @@ -183,8 +184,22 @@ } } } + + .remove { + display none + position absolute + right 10px + top 10px + } + + &:hover{ + .remove { + display block + } + } } + .animate { &:hover { box-shadow: 0 0 10px rgba(71, 255, 241, 0.6); /* 添加阴影效果 */