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(&param)
+	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