235 lines
5.6 KiB
Go
235 lines
5.6 KiB
Go
package middleware
|
||
|
||
import (
|
||
"encoding/json"
|
||
"errors"
|
||
"finclip-app-manager/infrastructure/client/httpcall"
|
||
"fmt"
|
||
"github.com/patrickmn/go-cache"
|
||
"net/http"
|
||
"strings"
|
||
//"sync"
|
||
"time"
|
||
|
||
"gitlab.finogeeks.club/finclip-backend/apm"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"github.com/zzfup/go-fetch"
|
||
)
|
||
|
||
var (
|
||
commonRsp CommonRspData
|
||
commonConfig CommonConfigData
|
||
//需要模糊匹配的url
|
||
needSkipUrlList = []string{"/api/v1/mop/finstore/ruleEngine/app"}
|
||
//确定的url
|
||
needSkipUrlMap = map[string]bool{
|
||
"/ready": true,
|
||
"/down": true,
|
||
"/test": true,
|
||
}
|
||
)
|
||
|
||
type CommonConfigData struct {
|
||
Error string `json:"error"`
|
||
Errcode string `json:"errcode"`
|
||
Data struct {
|
||
OrganName string `json:"organName"`
|
||
} `json:"data"`
|
||
}
|
||
|
||
type CommonRspData struct {
|
||
Error string `json:"error"`
|
||
Errcode string `json:"errcode"`
|
||
}
|
||
|
||
func getCommonConfig(c *gin.Context) error {
|
||
var headers = map[string]string{
|
||
"Accept": "application/json, text/plain, */*",
|
||
"Content-Type": "application/json",
|
||
"Connection": "close",
|
||
}
|
||
options := fetch.Options{
|
||
Method: "GET",
|
||
Header: headers,
|
||
}
|
||
|
||
url := "http://mop-private-init-server:8080/api/v1/mop/mop-private-init-server/common/config"
|
||
spanId := c.Request.Header.Get("Zipkin-Span-Id")
|
||
value := c.GetString("zipkin_trace_span_id_" + spanId)
|
||
options.Header["Zipkin-Span-Context"] = value
|
||
rsp, err := fetch.Fetch(url, options)
|
||
if err != nil || rsp.StatusCode != 200 {
|
||
return errors.New("mop-private-init-server err")
|
||
}
|
||
|
||
rsp.BindJSON(&commonConfig)
|
||
|
||
return nil
|
||
}
|
||
|
||
var licenseCache = cache.New(time.Hour, time.Minute)
|
||
|
||
//var licenseUrlMutex sync.Mutex
|
||
//var licenseMutex sync.Mutex
|
||
|
||
func CheckLicenseUrl(c *gin.Context) {
|
||
traceCtx := apm.ApmClient().TraceContextFromGin(c)
|
||
reqUrl := c.Request.URL.Path
|
||
if isNotNeedCheckLicenseConfUrl(reqUrl) {
|
||
c.Next()
|
||
return
|
||
}
|
||
type CheckUrlReq struct {
|
||
Url string `json:"url"`
|
||
Method string `json:"method"`
|
||
}
|
||
//文件名只拉取一次
|
||
if commonConfig.Data.OrganName == "" {
|
||
getCommonConfig(c)
|
||
}
|
||
var req CheckUrlReq
|
||
req.Url = reqUrl
|
||
req.Method = c.Request.Method
|
||
|
||
licenseCacheKey := "license_url_status_" + reqUrl
|
||
if code, ok := licenseCache.Get(licenseCacheKey); ok {
|
||
if code.(int) != 200 {
|
||
rspJson := gin.H{
|
||
"error": "license检测失败",
|
||
"errcode": "MOP_LICENSE_FORBINDDEN",
|
||
"data": nil,
|
||
}
|
||
c.AbortWithStatusJSON(http.StatusForbidden, rspJson)
|
||
return
|
||
}
|
||
c.Next()
|
||
return
|
||
}
|
||
|
||
//licenseUrlMutex.Lock()
|
||
//defer licenseUrlMutex.Unlock()
|
||
|
||
if code, ok := licenseCache.Get(licenseCacheKey); ok {
|
||
if code.(int) != 200 {
|
||
rspJson := gin.H{
|
||
"error": "license检测失败",
|
||
"errcode": "MOP_LICENSE_FORBINDDEN",
|
||
"data": nil,
|
||
}
|
||
c.AbortWithStatusJSON(http.StatusForbidden, rspJson)
|
||
return
|
||
}
|
||
c.Next()
|
||
return
|
||
}
|
||
|
||
var headers = map[string]string{
|
||
"Accept": "application/json, text/plain, */*",
|
||
"Content-Type": "application/json",
|
||
"Organ-Name": commonConfig.Data.OrganName, //私有化部署的时候,需要修改机构名称
|
||
"Connection": "close",
|
||
}
|
||
url := "http://mop-license-checker:8080/api/v1/mop/mop-license-checker/check/url"
|
||
rsp, err := httpcall.NewClient().Request(traceCtx).SetHeaders(headers).SetBody(req).Post(url)
|
||
|
||
if err != nil || rsp.StatusCode() != 200 {
|
||
if err != nil {
|
||
log.Errorf("check license url err:%+v", err)
|
||
rspJson := gin.H{
|
||
"error": "license检测失败",
|
||
"errcode": "MOP_LICENSE_FORBINDDEN",
|
||
"data": nil,
|
||
}
|
||
c.AbortWithStatusJSON(http.StatusForbidden, rspJson)
|
||
return
|
||
} else {
|
||
licenseCache.Set(licenseCacheKey, rsp.StatusCode(), 5*time.Minute)
|
||
}
|
||
json.Unmarshal(rsp.Body(), &commonRsp)
|
||
fmt.Printf("license code no 200 code=%d,rsp=%+v\n", rsp.StatusCode, rsp)
|
||
rspJson := gin.H{
|
||
"error": commonRsp.Error,
|
||
"errcode": commonRsp.Errcode,
|
||
"data": nil,
|
||
}
|
||
c.AbortWithStatusJSON(http.StatusForbidden, rspJson)
|
||
return
|
||
}
|
||
licenseCache.Set(licenseCacheKey, rsp.StatusCode(), 5*time.Minute)
|
||
c.Next()
|
||
}
|
||
|
||
func CheckLicenseConf(c *gin.Context) {
|
||
url := c.Request.URL.Path
|
||
if isNotNeedCheckLicenseConfUrl(url) {
|
||
c.Next()
|
||
return
|
||
}
|
||
|
||
licenseCacheKey := "license_exp"
|
||
if code, ok := licenseCache.Get(licenseCacheKey); ok {
|
||
if code.(int) != 1 {
|
||
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
|
||
"error": "操作失败,当前环境license已过期",
|
||
"errcode": "MOP_LICENSE_EXPIRED",
|
||
"data": make(map[string]interface{}),
|
||
})
|
||
return
|
||
}
|
||
c.Next()
|
||
return
|
||
}
|
||
|
||
//licenseMutex.Lock()
|
||
//defer licenseMutex.Unlock()
|
||
|
||
if code, ok := licenseCache.Get(licenseCacheKey); ok {
|
||
if code.(int) != 1 {
|
||
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
|
||
"error": "操作失败,当前环境license已过期",
|
||
"errcode": "MOP_LICENSE_EXPIRED",
|
||
"data": make(map[string]interface{}),
|
||
})
|
||
return
|
||
}
|
||
c.Next()
|
||
return
|
||
}
|
||
|
||
traceCtx := apm.ApmClient().TraceContextFromGin(c)
|
||
licenseInfo, err := hcaller.GetLicense(traceCtx)
|
||
if err != nil {
|
||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
|
||
"error": "license 请求错误",
|
||
"errcode": "NET_ERROR",
|
||
"data": make(map[string]interface{}),
|
||
})
|
||
return
|
||
}
|
||
if licenseInfo.ExpireTime < time.Now().UnixNano()/1e6 {
|
||
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
|
||
"error": "操作失败,当前环境license已过期",
|
||
"errcode": "MOP_LICENSE_EXPIRED",
|
||
"data": make(map[string]interface{}),
|
||
})
|
||
|
||
licenseCache.Set(licenseCacheKey, 0, 5*time.Minute)
|
||
return
|
||
}
|
||
|
||
licenseCache.Set(licenseCacheKey, 1, 5*time.Minute)
|
||
}
|
||
|
||
func isNotNeedCheckLicenseConfUrl(path string) bool {
|
||
if _, ok := needSkipUrlMap[path]; ok {
|
||
return true
|
||
}
|
||
for _, v := range needSkipUrlList {
|
||
if strings.Contains(path, v) {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|