From 1e7ef4a6705d59f7f3308638d44cc3b0cf340211 Mon Sep 17 00:00:00 2001 From: liujiandao <274878379@qq.com> Date: 星期四, 29 二月 2024 17:48:10 +0800 Subject: [PATCH] 登录与生丝定价 --- extend/code/code.go | 1 middleware/reset_pwd.go | 30 ++++ go.mod | 2 pkg/ecode/code.go | 1 middleware/jwt_request.go | 21 +++ models/raw_silk_price_standard.go | 96 +++++++++++++ router/router.go | 2 constvar/const.go | 8 + controllers/request/raw_silk_standard_request.go | 6 go.sum | 4 middleware/utils.go | 68 +++++++++ middleware/jwt.go | 101 +++----------- controllers/raw_silk_standard.go | 62 ++++++++ 13 files changed, 324 insertions(+), 78 deletions(-) diff --git a/constvar/const.go b/constvar/const.go index 16cb4da..34d9dc1 100644 --- a/constvar/const.go +++ b/constvar/const.go @@ -8,3 +8,11 @@ DictTypeColor //棰滆壊 DictTypeSpec //瑙勬牸 ) + +type UserType int + +const ( + UserTypeSuper UserType = iota + 1 // 瓒呯骇绠$悊鍛� + UserTypePrimary // 涓昏处鎴� + UserTypeSub // 瀛愯处鎴� +) diff --git a/controllers/raw_silk_standard.go b/controllers/raw_silk_standard.go new file mode 100644 index 0000000..2ab9dd2 --- /dev/null +++ b/controllers/raw_silk_standard.go @@ -0,0 +1,62 @@ +package controllers + +import ( + "github.com/gin-gonic/gin" + "silkserver/controllers/request" + "silkserver/extend/code" + "silkserver/extend/util" + "silkserver/models" +) + +type RawSilkStandardController struct { +} + +// SavePriceStandard +// +// @Tags 绯荤粺璁剧疆/鐢熶笣瀹氫环鏍囧噯 +// @Summary 淇濆瓨鐢熶笣瀹氫环鏍囧噯 +// @Produce application/json +// @Param object body models.RawSilkPriceStandard true "鍙傛暟" +// @Success 200 {object} util.Response "鎴愬姛" +// @Router /api-jl/v1/system/savePriceStandard [post] +func (slf RawSilkStandardController) SavePriceStandard(c *gin.Context) { + var priceStandard models.RawSilkPriceStandard + err := c.BindJSON(&priceStandard) + if err != nil { + util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�") + return + } + if priceStandard.ID > 0 { + err = models.NewRawSilkPriceStandardSearch().Save(&priceStandard) + } else { + err = models.NewRawSilkPriceStandardSearch().Create(&priceStandard) + } + if err != nil { + util.ResponseFormat(c, code.SaveFail, "淇濆瓨澶辫触") + return + } + util.ResponseFormat(c, code.Success, "淇濆瓨鎴愬姛") +} + +// GetPriceStandardList +// +// @Tags 绯荤粺璁剧疆/鐢熶笣瀹氫环鏍囧噯 +// @Summary 鑾峰彇鐢熶笣瀹氫环鏍囧噯 +// @Produce application/json +// @Param object body models.RawSilkPriceStandard true "鍙傛暟" +// @Success 200 {object} util.Response "鎴愬姛" +// @Router /api-jl/v1/system/getPriceStandardList [get] +func (slf RawSilkStandardController) GetPriceStandardList(c *gin.Context) { + var param request.GetPriceStandard + err := c.BindJSON(¶m) + if err != nil { + util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�") + return + } + list, total, err := models.NewRawSilkPriceStandardSearch().SetPage(param.Page, param.PageSize).Find() + if err != nil { + util.ResponseFormat(c, code.SelectError, "鏌ヨ澶辫触") + return + } + util.ResponseFormatList(c, code.Success, list, int(total)) +} diff --git a/controllers/request/raw_silk_standard_request.go b/controllers/request/raw_silk_standard_request.go new file mode 100644 index 0000000..dd0ebc5 --- /dev/null +++ b/controllers/request/raw_silk_standard_request.go @@ -0,0 +1,6 @@ +package request + +type GetPriceStandard struct { + PageInfo + KeyWord string `json:"keyWord"` +} diff --git a/extend/code/code.go b/extend/code/code.go index a7c4970..23016bf 100644 --- a/extend/code/code.go +++ b/extend/code/code.go @@ -25,4 +25,5 @@ NoTemplateError = &Code{3010, "鏈厤缃鍗曟ā鏉�"} InternalError = &Code{3011, "鍐呴儴閿欒"} NoProductionRequiredError = &Code{3012, "褰撳墠搴撳瓨婊¤冻姣涢渶姹傞噺锛屾殏鏃舵棤闇�杩涜鐢熶骇"} + SelectError = &Code{3013, "鏌ヨ澶辫触"} ) diff --git a/go.mod b/go.mod index 50f84b9..f0da53f 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,9 @@ basic.com/aps/nsqclient.git v0.0.0-20230517072415-37491f4a5d25 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/gin-gonic/gin v1.9.1 + github.com/golang-jwt/jwt/v4 v4.5.0 github.com/nsqio/go-nsq v1.1.0 + github.com/shopspring/decimal v1.3.1 github.com/spf13/viper v1.18.2 github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 diff --git a/go.sum b/go.sum index e3f7448..15dac96 100644 --- a/go.sum +++ b/go.sum @@ -50,6 +50,8 @@ github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= @@ -109,6 +111,8 @@ github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= diff --git a/middleware/jwt.go b/middleware/jwt.go index 8848c21..5d31ba9 100644 --- a/middleware/jwt.go +++ b/middleware/jwt.go @@ -1,94 +1,39 @@ package middleware import ( - "errors" - "fmt" - "silkserver/conf" - "strings" - "time" - - jwt "github.com/dgrijalva/jwt-go" "github.com/gin-gonic/gin" - "silkserver/extend/util" + "silkserver/pkg/contextx" + "silkserver/pkg/ecode" + "strings" ) -func validateToken(tokenString string) (util.JSON, error) { - secretKey := []byte(conf.WebConf.JWTSecret) - - token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { - // Don't forget to validate the alg is what you expect: - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) - } - - return secretKey, nil - }) - - if err != nil { - return util.JSON{}, err - } - - if !token.Valid { - return util.JSON{}, errors.New("invalid token") - } - - return token.Claims.(jwt.MapClaims), nil -} - -// JWTMiddleware parses JWT token from cookie and stores data and expires date to the context -// JWT Token can be passed as cookie, or Authorization header -func JWTMiddleware() gin.HandlerFunc { +func JWTAuth() gin.HandlerFunc { return func(c *gin.Context) { - tokenString, err := c.Cookie("token") - // failed to read cookie - if err != nil { - // try reading HTTP Header - authorization := c.Request.Header.Get("Authorization") - if authorization == "" { - c.Next() - return - } - sp := strings.Split(authorization, "Bearer ") - // invalid token - if len(sp) < 1 { - c.Next() - return - } - tokenString = sp[1] + ctx := new(contextx.Context).SetCtx(c) + // 鎴戜滑杩欓噷jwt閴存潈鍙栧ご閮ㄤ俊鎭� Authorization 鐧诲綍鏃跺洖杩斿洖token淇℃伅 杩欓噷鍓嶇闇�瑕佹妸token瀛樺偍鍒癱ookie鎴栬�呮湰鍦發ocalStorage涓� 涓嶈繃闇�瑕佽窡鍚庣鍗忓晢杩囨湡鏃堕棿 鍙互绾﹀畾鍒锋柊浠ょ墝鎴栬�呴噸鏂扮櫥褰� + token := c.Request.Header.Get("Authorization") + if token == "" { + ctx.Fail(ecode.JWTEmpty) + c.Abort() + return } - - tokenData, err := validateToken(tokenString) + slices := strings.Split(token, " ") + if len(slices) == 2 { + token = slices[1] + } + j := NewJWT() + // parseToken 瑙f瀽token鍖呭惈鐨勪俊鎭� + claims, err := j.ParseToken(token) if err != nil { - fmt.Println(err.Error()) + if err == TokenExpired { + c.Next() + return + } c.Next() return } - userParentId := tokenData["parentId"].(string) - if userParentId == conf.WebConf.NodeId { - c.Set("parentId", userParentId) - } else { - c.Next() - return - } - - c.Set("token_expire", tokenData["exp"]) + c.Set("claims", claims) c.Next() } -} - -func GenerateToken(data interface{}) (string, error) { - // token is valid for 1 hour - date := time.Now().Add(time.Hour * 12) - - token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ - "user": data, - "exp": date.Unix(), - }) - - secretKey := []byte(conf.WebConf.JWTSecret) - - tokenString, err := token.SignedString(secretKey) - - return tokenString, err } diff --git a/middleware/jwt_request.go b/middleware/jwt_request.go new file mode 100644 index 0000000..070280d --- /dev/null +++ b/middleware/jwt_request.go @@ -0,0 +1,21 @@ +package middleware + +import ( + "github.com/dgrijalva/jwt-go" + "silkserver/constvar" +) + +// Custom claims structure +type CustomClaims struct { + BaseClaims + BufferTime int64 + jwt.StandardClaims +} + +type BaseClaims struct { + UserId string + Username string + ParentId string + UserType constvar.UserType + ModifiedPwd *bool +} diff --git a/middleware/reset_pwd.go b/middleware/reset_pwd.go new file mode 100644 index 0000000..2d7f7e8 --- /dev/null +++ b/middleware/reset_pwd.go @@ -0,0 +1,30 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" + "silkserver/pkg/contextx" + "silkserver/pkg/ecode" +) + +func VerifyResetPwd() gin.HandlerFunc { + return func(c *gin.Context) { + ctx := new(contextx.Context).SetCtx(c) + params, ok := c.Get("claims") + if !ok { + c.Abort() + return + } + claims := params.(*CustomClaims) + if claims.ModifiedPwd == nil { //鍏煎娌℃湁ModifiedPwd鍊肩殑token + ctx.Fail(ecode.JWTExpire) + c.Abort() + return + } + + if !*claims.ModifiedPwd { + ctx.Fail(ecode.ResetPwd) + c.Abort() + return + } + } +} diff --git a/middleware/utils.go b/middleware/utils.go new file mode 100644 index 0000000..848d2d8 --- /dev/null +++ b/middleware/utils.go @@ -0,0 +1,68 @@ +package middleware + +import ( + "errors" + "github.com/gin-gonic/gin" + "github.com/golang-jwt/jwt/v4" +) + +type JWT struct { + SigningKey []byte +} + +var ( + TokenExpired = errors.New("Token is expired") + TokenNotValidYet = errors.New("Token not active yet") + TokenMalformed = errors.New("That's not even a token") + TokenInvalid = errors.New("Couldn't handle this token:") +) + +func NewJWT() *JWT { + return &JWT{ + []byte("327a9457-899a-481e-8b30-58cc97e5b808"), + } +} + +// CreateToken 鍒涘缓涓�涓猼oken +func (j *JWT) CreateToken(claims CustomClaims) (string, error) { + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + return token.SignedString(j.SigningKey) +} + +// ParseToken 瑙f瀽token +func (j *JWT) ParseToken(tokenString string) (*CustomClaims, error) { + token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (i interface{}, e error) { + return j.SigningKey, nil + }) + if err != nil { + if ve, ok := err.(*jwt.ValidationError); ok { + if ve.Errors&jwt.ValidationErrorMalformed != 0 { + return nil, TokenMalformed + } else if ve.Errors&jwt.ValidationErrorExpired != 0 { + // Token is expired + return nil, TokenExpired + } else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 { + return nil, TokenNotValidYet + } else { + return nil, TokenInvalid + } + } + } + if token != nil { + if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid { + return claims, nil + } + return nil, TokenInvalid + + } else { + return nil, TokenInvalid + } +} + +func GetUserInfo(c *gin.Context) *CustomClaims { + if claims, exists := c.Get("claims"); exists { + waitUse := claims.(*CustomClaims) + return waitUse + } + return nil +} diff --git a/models/raw_silk_price_standard.go b/models/raw_silk_price_standard.go new file mode 100644 index 0000000..7f3dea5 --- /dev/null +++ b/models/raw_silk_price_standard.go @@ -0,0 +1,96 @@ +package models + +import ( + "fmt" + "github.com/shopspring/decimal" + "gorm.io/gorm" + "silkserver/pkg/mysqlx" +) + +// RawSilkPriceStandard +type ( + RawSilkPriceStandard struct { + gorm.Model + MarketNumber string `json:"marketNumber" gorm:"type:varchar(255);comment:搴勫彛缂栧彿"` + RawSilkGradeNumber string `json:"rawSilkGradeNumber" gorm:"type:varchar(255);comment:鐢熶笣绛夌骇缂栧彿"` + PayStandard decimal.Decimal `json:"payStandard" gorm:"type:decimal(20,3);comment:钖叕鏍囧噯"` + Unit string `json:"unit" gorm:"type:varchar(100);comment:鍗曚綅"` + Notes string `json:"notes" gorm:"type:varchar(255);comment:澶囨敞"` + } + RawSilkPriceStandardSearch struct { + RawSilkPriceStandard + Order string + PageNum int + PageSize int + Orm *gorm.DB + } +) + +func (slf RawSilkPriceStandard) TableName() string { + return "raw_silk_price_standard" +} + +func NewRawSilkPriceStandardSearch() *RawSilkPriceStandardSearch { + return &RawSilkPriceStandardSearch{Orm: mysqlx.GetDB()} +} + +func (slf *RawSilkPriceStandardSearch) SetOrm(tx *gorm.DB) *RawSilkPriceStandardSearch { + slf.Orm = tx + return slf +} + +func (slf *RawSilkPriceStandardSearch) SetPage(page, size int) *RawSilkPriceStandardSearch { + slf.PageNum, slf.PageSize = page, size + return slf +} + +func (slf *RawSilkPriceStandardSearch) SetOrder(order string) *RawSilkPriceStandardSearch { + slf.Order = order + return slf +} + +func (slf *RawSilkPriceStandardSearch) build() *gorm.DB { + db := slf.Orm.Table(slf.TableName()) + + return db +} + +// Create 鍗曟潯鎻掑叆 +func (slf *RawSilkPriceStandardSearch) Create(record *RawSilkPriceStandard) error { + db := slf.build() + err := db.Create(record).Error + if err != nil { + return fmt.Errorf("create err: %v, record: %+v", err, record) + } + return nil +} + +func (slf *RawSilkPriceStandardSearch) Find() ([]*RawSilkPriceStandard, int64, error) { + var ( + records = make([]*RawSilkPriceStandard, 0) + total int64 + db = slf.build() + ) + + if err := db.Count(&total).Error; err != nil { + return records, total, fmt.Errorf("find count err: %v", err) + } + if slf.PageNum*slf.PageSize > 0 { + db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize) + } + if err := db.Find(&records).Error; err != nil { + return records, total, fmt.Errorf("find records err: %v", err) + } + + return records, total, nil +} + +func (slf *RawSilkPriceStandardSearch) Save(record *RawSilkPriceStandard) error { + var db = slf.build() + + if err := db.Save(record).Error; err != nil { + return fmt.Errorf("save err: %v, record: %+v", err, record) + } + + return nil +} diff --git a/pkg/ecode/code.go b/pkg/ecode/code.go index aa74251..d7fd60b 100644 --- a/pkg/ecode/code.go +++ b/pkg/ecode/code.go @@ -18,4 +18,5 @@ JWTEmpty = 2013 // JWT涓虹┖ JWTExpire = 2014 // JWT杩囨湡 JWTParseErr = 2015 // JWT瑙f瀽澶辫触 + ResetPwd = 2036 //璐﹀彿璁剧疆瀵嗙爜 ) diff --git a/router/router.go b/router/router.go index ebf1ae3..65fec3c 100644 --- a/router/router.go +++ b/router/router.go @@ -18,6 +18,8 @@ r.StaticFS(conf.LocalConf.StorePath, http.Dir(conf.LocalConf.StorePath)) // 涓虹敤鎴峰ご鍍忓拰鏂囦欢鎻愪緵闈欐�佸湴鍧� r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) + r.Use(middleware.JWTAuth()) + r.Use(middleware.VerifyResetPwd()) urlPrefix := "/api-jl/v1" -- Gitblit v1.8.0