Browse Source

check header

shao 2 weeks ago
parent
commit
47ae66752b
8 changed files with 168 additions and 17 deletions
  1. 13 0
      api/v1/public.go
  2. 19 0
      common/config.go
  3. 72 8
      common/enum.go
  4. 8 0
      common/rescode.go
  5. 1 1
      common/response.go
  6. 6 2
      config/config.toml.template
  7. 48 6
      router/middleware.go
  8. 1 0
      router/router.go

+ 13 - 0
api/v1/public.go

@@ -13,6 +13,19 @@ func Ping(c *gin.Context) {
 	common.HttpSuccess(c, "ping")
 }
 
+func SoftwareInfo(c *gin.Context) {
+	common.HttpSuccess(c, map[string]interface{}{
+		"server": map[string]interface{}{
+			"resource-server": map[string]interface{}{
+				"desc":    common.Desc,
+				"build":   common.Build,
+				"version": common.Version,
+			},
+		},
+		"language": common.MetadataConfig.GetLanguages(),
+	})
+}
+
 func Login(c *gin.Context) {
 	request := &struct {
 		Username string `json:"username" binding:"required"`

+ 19 - 0
common/config.go

@@ -62,12 +62,20 @@ type postgres struct {
 // metadata配置
 type metadata struct {
 	Languages []Lang
+	Product   Product
+	Sources   []Source
 }
 
 func (p *metadata) setup() {
 	if !ValidLanguages(p.Languages) {
 		panic(fmt.Sprintf("invalid languages, optional values are: %v", AllLanguages()))
 	}
+	if !ValidProduct(p.Product) {
+		panic(fmt.Sprintf("invalid product, optional values are: %v", AllProducts()))
+	}
+	if !ValidSources(p.Sources) {
+		panic(fmt.Sprintf("invalid sources, optional values are: %v", AllSources()))
+	}
 }
 
 func (p *metadata) GetLanguages() []Lang {
@@ -77,6 +85,17 @@ func (p *metadata) GetLanguages() []Lang {
 	return p.Languages
 }
 
+func (p *metadata) GetProduct() Product {
+	return p.Product
+}
+
+func (p *metadata) GetSources() []Source {
+	if len(p.Sources) == 0 {
+		return AllSources()
+	}
+	return p.Sources
+}
+
 func InitApplication() *application {
 	return &application{
 		Host: viper.GetString("host"),

+ 72 - 8
common/enum.go

@@ -3,23 +3,24 @@ package common
 type Lang string
 
 const (
-	Lang_en Lang = "en"
-	Lang_zh Lang = "zh"
+	LANG_EN Lang = "en"
+	LANG_ZH Lang = "zh"
 )
 
-func (p Lang) toString() string {
+func (p Lang) ToString() string {
 	switch p {
-	case Lang_en:
+	case LANG_EN:
 		return "en"
-	case Lang_zh:
+	case LANG_ZH:
 		return "zh"
+	default:
+		return ""
 	}
-	return ""
 }
 
 func ValidLanguages(langs []Lang) bool {
 	for _, lang := range langs {
-		if lang.toString() == "" {
+		if lang.ToString() == "" {
 			return false
 		}
 	}
@@ -27,5 +28,68 @@ func ValidLanguages(langs []Lang) bool {
 }
 
 func AllLanguages() []Lang {
-	return []Lang{Lang_en, Lang_zh}
+	return []Lang{LANG_EN, LANG_ZH}
+}
+
+type Source string
+
+const (
+	SOURCE_GUI     Source = "gui"
+	SOURCE_BROWSER Source = "browser"
+	SOURCE_ANDROID Source = "android"
+	SOURCE_DEV     Source = "dev"
+)
+
+func (p Source) ToString() string {
+	switch p {
+	case SOURCE_GUI:
+		return "gui"
+	case SOURCE_BROWSER:
+		return "browser"
+	case SOURCE_ANDROID:
+		return "android"
+	case SOURCE_DEV:
+		return "dev"
+	default:
+		return ""
+	}
+}
+
+func ValidSources(sources []Source) bool {
+	for _, source := range sources {
+		if source.ToString() == "" {
+			return false
+		}
+	}
+	return true
+}
+
+func AllSources() []Source {
+	return []Source{SOURCE_GUI, SOURCE_BROWSER, SOURCE_ANDROID, SOURCE_DEV}
+}
+
+type Product string
+
+const (
+	PRODUCT_DROC Product = "droc"
+	PRODUCT_VET  Product = "vetdroc"
+)
+
+func (p Product) ToString() string {
+	switch p {
+	case PRODUCT_DROC:
+		return "droc"
+	case PRODUCT_VET:
+		return "vetdroc"
+	default:
+		return ""
+	}
+}
+
+func ValidProduct(product Product) bool {
+	return product.ToString() != ""
+}
+
+func AllProducts() []Product {
+	return []Product{PRODUCT_DROC, PRODUCT_VET}
 }

+ 8 - 0
common/rescode.go

@@ -30,6 +30,10 @@ var (
 	NotAvailableError ResDesc = "ErrCode_NotAvailableError"
 	UnknownError      ResDesc = "ErrCode_UnknownError"
 
+	InvalidLanguageError ResDesc = "ErrCode_InvalidLanguageError"
+	InvalidSourceError   ResDesc = "ErrCode_InvalidSourceError"
+	InvalidProductError  ResDesc = "ErrCode_InvalidProductError"
+
 	// 业务 错误
 	InvalidIdError ResDesc = "InvalidIdError"
 	FieldTypeError ResDesc = "FieldTypeError"
@@ -47,6 +51,10 @@ var (
 	Exists       = &ResStatus{Code: "0x000107", Description: ExistsError, Solution: ""}
 	NotAvailable = &ResStatus{Code: "0x000108", Description: NotAvailableError, Solution: ""}
 
+	InvalidLanguage = &ResStatus{Code: "0x000111", Description: InvalidLanguageError, Solution: ""}
+	InvalidSource   = &ResStatus{Code: "0x000112", Description: InvalidSourceError, Solution: ""}
+	InvalidProduct  = &ResStatus{Code: "0x000113", Description: InvalidProductError, Solution: ""}
+
 	InvalidUsernameOrPasswd = &ResStatus{Code: "0x010101", Description: "ErrCode_InvalidUsernameOrPasswdError", Solution: ""}
 
 	Unknown = &ResStatus{Code: "0x999999", Description: UnknownError, Solution: ""}

+ 1 - 1
common/response.go

@@ -21,7 +21,7 @@ import (
 
 func HttpSuccess(c *gin.Context, data ...interface{}) {
 	if len(data) > 0 {
-		c.JSON(http.StatusOK, OK.H(data[0]))
+		c.JSON(http.StatusOK, OK.Translator(GetTrans(c.GetHeader("Language"))).H(data[0]))
 	} else {
 		c.JSON(http.StatusOK, OK.H())
 	}

+ 6 - 2
config/config.toml.template

@@ -27,5 +27,9 @@ password = "123456"
 name = "mytestdatabase"
 
 [metadata]
-# 支持的语言,可选项:"zh"
-languages = ["zh"]
+# 支持的语言,可选项:"en","zh"
+languages = ["en", "zh"]
+# 支持的产品,可选项:"droc","vetdroc"
+product = "vetdroc"
+# 支持的访问源,可选项:"gui","browser","android"
+sources = ["gui", "browser", "android"]

+ 48 - 6
router/middleware.go

@@ -29,6 +29,10 @@ func InitMiddleware(r *gin.Engine) {
 	r.Use(GinLogger(logger.WithGroup("gin")))
 	// Global Recover
 	r.Use(GinRecovery(logger.WithGroup("ginRecovery")))
+	// check header
+	r.Use(CheckLanguage)
+	r.Use(CheckSource)
+	r.Use(CheckProduct)
 	// check token
 	r.Use(CheckAuth)
 }
@@ -73,13 +77,51 @@ func Secure(c *gin.Context) {
 	// c.Header("Content-Security-Policy", "script-src 'self' https://cdnjs.cloudflare.com")
 }
 
+func CheckLanguage(c *gin.Context) {
+	ok := false
+	language := c.Request.Header.Get("Language")
+	for _, l := range common.MetadataConfig.GetLanguages() {
+		slog.Info("----------", "language", l)
+		if language == l.ToString() {
+			ok = true
+		}
+	}
+	slog.Info("----------", "language", language, "ok", ok)
+	if !ok {
+		c.AbortWithStatusJSON(200, common.ErrToH(common.InvalidLanguage, c.GetHeader("locale")))
+	} else {
+		c.Set("language", language)
+	}
+	c.Next()
+}
+
+func CheckSource(c *gin.Context) {
+	source := c.Request.Header.Get("Source")
+	ok := false
+	for _, s := range common.MetadataConfig.GetSources() {
+		if source == s.ToString() {
+			ok = true
+		}
+	}
+	if !ok {
+		c.AbortWithStatusJSON(200, common.ErrToH(common.InvalidSource, c.GetHeader("locale")))
+	} else {
+		c.Set("source", source)
+	}
+	c.Next()
+}
+
+func CheckProduct(c *gin.Context) {
+	product := c.Request.Header.Get("Product")
+	if product != common.MetadataConfig.GetProduct().ToString() {
+		c.AbortWithStatusJSON(200, common.ErrToH(common.InvalidProduct, product))
+	} else {
+		c.Set("product", product)
+	}
+	c.Next()
+}
+
 func CheckAuth(c *gin.Context) {
-	//if common.Hostname == "DESKTOP-2VF4H05" {
-	//	c.Set("uid", cast.ToUint(1))
-	//	c.Set("username", "dev")
-	//	c.Next()
-	//	return
-	//}
 	if strings.HasPrefix(c.FullPath(), "/dr/api/v1/auth") {
 		token := c.Request.Header.Get("Authorization")
 		uid, username, err := common.ParseToken(strings.TrimPrefix(token, "Bearer "))

+ 1 - 0
router/router.go

@@ -19,6 +19,7 @@ func InitRouter() *gin.Engine {
 	pubV1 := v1.Group("/pub")
 	{
 		pubV1.GET("/ping", apiv1.Ping)
+		pubV1.GET("software_info", apiv1.SoftwareInfo)
 		pubV1.POST("login", apiv1.Login)
 	}
 	authV1 := v1.Group("/auth")