mirror of
https://gitee.com/XM-GO/PandaX.git
synced 2026-04-23 02:48:34 +08:00
Merge branch 'iot'
# Conflicts: # apps/develop/api/gen.go # apps/develop/api/table.go # apps/develop/router/gen.go # apps/develop/router/table.go # apps/job/api/job.go # apps/job/entity/job.go # apps/job/entity/log_job.go # apps/job/jobs/jobbase.go # apps/job/router/job.go # apps/log/api/log_job.go # apps/log/api/log_login.go # apps/log/api/log_oper.go # apps/log/router/log.go # apps/log/services/log_job.go # apps/resource/api/email.go # apps/resource/api/oss.go # apps/resource/router/email.go # apps/resource/router/oss.go # apps/system/api/api.go # apps/system/api/config.go # apps/system/api/dept.go # apps/system/api/dict.go # apps/system/api/menu.go # apps/system/api/notice.go # apps/system/api/post.go # apps/system/api/role.go # apps/system/api/system.go # apps/system/api/tenant.go # apps/system/api/user.go # apps/system/router/api.go # apps/system/router/config.go # apps/system/router/dept.go # apps/system/router/dict.go # apps/system/router/menu.go # apps/system/router/notice.go # apps/system/router/post.go # apps/system/router/role.go # apps/system/router/tenant.go # apps/system/router/user.go # go.mod # go.sum # main.go # pkg/config/app.go # pkg/config/casbin.go # pkg/config/config.go # pkg/config/db.go # pkg/config/gen.go # pkg/config/jwt.go # pkg/config/log.go # pkg/config/redis.go # pkg/config/server.go # pkg/global/global.go # pkg/initialize/table.go # pkg/middleware/log.go # pkg/middleware/oper.go # pkg/middleware/permission.go # resource/template/go/api.template # resource/template/go/router.template # resource/template/go/service.template
This commit is contained in:
@@ -1,27 +1,17 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
)
|
||||
|
||||
// 处理跨域请求,支持options访问
|
||||
func Cors() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
method := c.Request.Method
|
||||
origin := c.Request.Header.Get("Origin")
|
||||
c.Header("Access-Control-Allow-Origin", origin)
|
||||
c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id")
|
||||
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS,DELETE,PUT")
|
||||
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
|
||||
c.Header("Access-Control-Allow-Credentials", "true")
|
||||
func Cors(wsContainer *restful.Container) restful.CrossOriginResourceSharing {
|
||||
cors := restful.CrossOriginResourceSharing{
|
||||
ExposeHeaders: []string{"Content-Length", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
|
||||
AllowedHeaders: []string{"Content-Type", "AccessToken", "X-CSRF-Token", "Authorization", "Token", "X-Token", "X-User-Id"},
|
||||
AllowedMethods: []string{"POST", "GET", "OPTIONS", "DELETE", "PUT"},
|
||||
CookiesAllowed: false,
|
||||
Container: wsContainer}
|
||||
|
||||
// 放行所有OPTIONS方法
|
||||
if method == "OPTIONS" {
|
||||
c.AbortWithStatus(http.StatusNoContent)
|
||||
}
|
||||
// 处理请求
|
||||
c.Next()
|
||||
}
|
||||
return cors
|
||||
}
|
||||
|
||||
17
pkg/middleware/escape_html.go
Normal file
17
pkg/middleware/escape_html.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
"html"
|
||||
)
|
||||
|
||||
// 防止XSS攻击
|
||||
func EscapeHTML(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
|
||||
// 获取请求参数中的HTML标签
|
||||
for _, p := range req.Request.URL.Query() {
|
||||
escaped := html.EscapeString(p[0])
|
||||
// 将转义后的参数重新设置到请求参数中
|
||||
req.Request.URL.Query().Set(p[0], escaped)
|
||||
}
|
||||
chain.ProcessFilter(req, resp)
|
||||
}
|
||||
70
pkg/middleware/log.go
Normal file
70
pkg/middleware/log.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/XM-GO/PandaKit/biz"
|
||||
"github.com/XM-GO/PandaKit/logger"
|
||||
"github.com/XM-GO/PandaKit/restfulx"
|
||||
"github.com/XM-GO/PandaKit/utils"
|
||||
"github.com/sirupsen/logrus"
|
||||
"reflect"
|
||||
"runtime/debug"
|
||||
)
|
||||
|
||||
func LogHandler(rc *restfulx.ReqCtx) error {
|
||||
li := rc.LogInfo
|
||||
if li == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
lfs := logrus.Fields{}
|
||||
if la := rc.LoginAccount; la != nil {
|
||||
lfs["uid"] = la.UserId
|
||||
lfs["uname"] = la.UserName
|
||||
}
|
||||
|
||||
req := rc.Request.Request
|
||||
lfs[req.Method] = req.URL.Path
|
||||
|
||||
if err := rc.Err; err != nil {
|
||||
logger.Log.WithFields(lfs).Error(getErrMsg(rc, err))
|
||||
return nil
|
||||
}
|
||||
logger.Log.WithFields(lfs).Info(getLogMsg(rc))
|
||||
return nil
|
||||
}
|
||||
|
||||
func getLogMsg(rc *restfulx.ReqCtx) string {
|
||||
msg := rc.LogInfo.Description + fmt.Sprintf(" ->%dms", rc.Timed)
|
||||
if !utils.IsBlank(reflect.ValueOf(rc.ReqParam)) {
|
||||
rb, _ := json.Marshal(rc.ReqParam)
|
||||
msg = msg + fmt.Sprintf("\n--> %s", string(rb))
|
||||
}
|
||||
|
||||
// 返回结果不为空,则记录返回结果
|
||||
if rc.LogInfo.LogResp && !utils.IsBlank(reflect.ValueOf(rc.ResData)) {
|
||||
respB, _ := json.Marshal(rc.ResData)
|
||||
msg = msg + fmt.Sprintf("\n<-- %s", string(respB))
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
func getErrMsg(rc *restfulx.ReqCtx, err any) string {
|
||||
msg := rc.LogInfo.Description
|
||||
if !utils.IsBlank(reflect.ValueOf(rc.ReqParam)) {
|
||||
rb, _ := json.Marshal(rc.ReqParam)
|
||||
msg = msg + fmt.Sprintf("\n--> %s", string(rb))
|
||||
}
|
||||
|
||||
var errMsg string
|
||||
switch t := err.(type) {
|
||||
case *biz.BizError:
|
||||
errMsg = fmt.Sprintf("\n<-e errCode: %d, errMsg: %s", t.Code(), t.Error())
|
||||
case error:
|
||||
errMsg = fmt.Sprintf("\n<-e errMsg: %s\n%s", t.Error(), string(debug.Stack()))
|
||||
case string:
|
||||
errMsg = fmt.Sprintf("\n<-e errMsg: %s\n%s", t, string(debug.Stack()))
|
||||
}
|
||||
return (msg + errMsg)
|
||||
}
|
||||
46
pkg/middleware/permission.go
Normal file
46
pkg/middleware/permission.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/XM-GO/PandaKit/biz"
|
||||
"github.com/XM-GO/PandaKit/casbin"
|
||||
"github.com/XM-GO/PandaKit/restfulx"
|
||||
"github.com/XM-GO/PandaKit/token"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"pandax/pkg/global"
|
||||
)
|
||||
|
||||
func PermissionHandler(rc *restfulx.ReqCtx) error {
|
||||
permission := rc.RequiredPermission
|
||||
// 如果需要的权限信息不为空,并且不需要token,则不返回错误,继续后续逻辑
|
||||
if permission != nil && !permission.NeedToken {
|
||||
return nil
|
||||
}
|
||||
tokenStr := rc.Request.Request.Header.Get("X-TOKEN")
|
||||
// header不存在则从查询参数token中获取
|
||||
if tokenStr == "" {
|
||||
tokenStr = rc.Request.QueryParameter("token")
|
||||
}
|
||||
if tokenStr == "" {
|
||||
return biz.PermissionErr
|
||||
}
|
||||
j := token.NewJWT("", []byte(global.Conf.Jwt.Key), jwt.SigningMethodHS256)
|
||||
loginAccount, err := j.ParseToken(tokenStr)
|
||||
if err != nil || loginAccount == nil {
|
||||
return biz.PermissionErr
|
||||
}
|
||||
rc.LoginAccount = loginAccount
|
||||
|
||||
if !permission.NeedCasbin {
|
||||
return nil
|
||||
}
|
||||
|
||||
ca := casbin.CasbinS{ModelPath: global.Conf.Casbin.ModelPath}
|
||||
e := ca.Casbin()
|
||||
// 判断策略中是否存在
|
||||
success, err := e.Enforce(loginAccount.RoleKey, rc.Request.Request.URL.Path, rc.Request.Request.Method)
|
||||
if !success {
|
||||
return biz.CasbinErr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package middleware
|
||||
|
||||
import (
|
||||
"github.com/didip/tollbooth"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
"pandax/pkg/global"
|
||||
)
|
||||
|
||||
@@ -12,17 +12,14 @@ import (
|
||||
* @Date 2022/1/19 8:28
|
||||
**/
|
||||
|
||||
//限流中间件
|
||||
func Rate() gin.HandlerFunc {
|
||||
//Rate 限流中间件
|
||||
func Rate(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
|
||||
lmt := tollbooth.NewLimiter(global.Conf.Server.Rate.RateNum, nil)
|
||||
lmt.SetMessage("已经超出接口请求限制,稍后再试.")
|
||||
return func(c *gin.Context) {
|
||||
httpError := tollbooth.LimitByRequest(lmt, c.Writer, c.Request)
|
||||
if httpError != nil {
|
||||
c.Data(httpError.StatusCode, lmt.GetMessageContentType(), []byte(httpError.Message))
|
||||
c.Abort()
|
||||
} else {
|
||||
c.Next()
|
||||
}
|
||||
httpError := tollbooth.LimitByRequest(lmt, resp, req.Request)
|
||||
if httpError != nil {
|
||||
resp.WriteErrorString(httpError.StatusCode, httpError.Message)
|
||||
return
|
||||
}
|
||||
chain.ProcessFilter(req, resp)
|
||||
}
|
||||
|
||||
44
pkg/middleware/swagger.go
Normal file
44
pkg/middleware/swagger.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
restfulspec "github.com/emicklei/go-restful-openapi/v2"
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
/**
|
||||
* @Description
|
||||
* @Author 熊猫
|
||||
* @Date 2022/8/3 9:16
|
||||
**/
|
||||
|
||||
func SwaggerConfig(wsContainer *restful.Container) {
|
||||
config := restfulspec.Config{
|
||||
WebServices: wsContainer.RegisteredWebServices(),
|
||||
APIPath: "/apidocs.json",
|
||||
PostBuildSwaggerObjectHandler: enrichSwaggerObject}
|
||||
wsContainer.Add(restfulspec.NewOpenAPIService(config))
|
||||
}
|
||||
|
||||
func enrichSwaggerObject(swo *spec.Swagger) {
|
||||
swo.Info = &spec.Info{
|
||||
InfoProps: spec.InfoProps{
|
||||
Title: "PandaX 框架的API文档",
|
||||
Description: "这是PandaX框架文档,根据文档调用API",
|
||||
Contact: &spec.ContactInfo{
|
||||
ContactInfoProps: spec.ContactInfoProps{
|
||||
Name: "PandaX 熊猫",
|
||||
Email: "2417920382@qq.com",
|
||||
URL: "https://github.com/XM-GO/PandaX",
|
||||
},
|
||||
},
|
||||
License: &spec.License{
|
||||
LicenseProps: spec.LicenseProps{
|
||||
Name: "MIT",
|
||||
URL: "https://github.com/XM-GO/PandaX",
|
||||
},
|
||||
},
|
||||
Version: "1.0.0",
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user