瀏覽代碼

add local support

infish2018 1 月之前
父節點
當前提交
f566f7ab78
共有 100 個文件被更改,包括 961 次插入172 次删除
  1. 1 0
      .gitignore
  2. 0 3
      .gitmodules
  3. 156 0
      src/api/admin.go
  4. 27 19
      src/api/api.go
  5. 0 31
      src/api/callback.go
  6. 2 2
      src/api/case.go
  7. 1 1
      src/api/category.go
  8. 143 0
      src/api/client.go
  9. 190 49
      src/api/controller.go
  10. 172 0
      src/api/jwt.go
  11. 11 1
      src/api/router.go
  12. 50 0
      src/api/upload.go
  13. 2 5
      src/db/db.go
  14. 31 21
      src/go.mod
  15. 88 35
      src/go.sum
  16. 4 5
      src/main.go
  17. 80 0
      src/start_mongodb.go
  18. 0 0
      src/static/css/240.05f7c25f.css
  19. 0 0
      src/static/css/240.9cec3cf6.css
  20. 0 0
      src/static/css/278.b4c3c5ef.css
  21. 0 0
      src/static/css/301.335fe4b6.css
  22. 0 0
      src/static/css/301.d5d05c9f.css
  23. 0 0
      src/static/css/314.0514518c.css
  24. 0 0
      src/static/css/314.9df3d594.css
  25. 0 0
      src/static/css/331.18d162f5.css
  26. 0 0
      src/static/css/331.1dc3bf48.css
  27. 0 0
      src/static/css/335.b8c109e0.css
  28. 0 0
      src/static/css/460.900a8fe0.css
  29. 0 0
      src/static/css/460.ba801ed4.css
  30. 0 0
      src/static/css/493.d92bcb46.css
  31. 0 0
      src/static/css/493.d985bd14.css
  32. 0 0
      src/static/css/533.1d4799b3.css
  33. 0 0
      src/static/css/533.bc4d415e.css
  34. 0 0
      src/static/css/64.335fe4b6.css
  35. 0 0
      src/static/css/64.d5d05c9f.css
  36. 0 0
      src/static/css/641.038fcf15.css
  37. 0 0
      src/static/css/641.2c0a1f91.css
  38. 1 0
      src/static/css/986.03005caf.css
  39. 1 0
      src/static/css/986.253c887d.css
  40. 0 0
      src/static/css/chunk-vendors.56e805c9.css
  41. 0 0
      src/static/css/chunk-vendors.c2ac48b0.css
  42. 0 0
      src/static/css/index.77a408e1.css
  43. 0 0
      src/static/css/index.bd9dc691.css
  44. 二進制
      src/static/favicon.ico
  45. 二進制
      src/static/img/banner.97a62f46.png
  46. 二進制
      src/static/img/bg.89607e29.png
  47. 1 0
      src/static/index.html
  48. 0 0
      src/static/js/240.10a5987f.js
  49. 0 0
      src/static/js/240.10a5987f.js.map
  50. 0 0
      src/static/js/240.30f55128.js
  51. 0 0
      src/static/js/240.30f55128.js.map
  52. 0 0
      src/static/js/278.0c4c9e36.js
  53. 0 0
      src/static/js/278.0c4c9e36.js.map
  54. 0 0
      src/static/js/301.6732d5fb.js
  55. 0 0
      src/static/js/301.6732d5fb.js.map
  56. 0 0
      src/static/js/301.a5f6d222.js
  57. 0 0
      src/static/js/301.a5f6d222.js.map
  58. 0 0
      src/static/js/314.720c7ad1.js
  59. 0 0
      src/static/js/314.720c7ad1.js.map
  60. 0 0
      src/static/js/314.a21616f1.js
  61. 0 0
      src/static/js/314.a21616f1.js.map
  62. 0 0
      src/static/js/331.303036ef.js
  63. 0 0
      src/static/js/331.303036ef.js.map
  64. 0 0
      src/static/js/331.37c87581.js
  65. 0 0
      src/static/js/331.37c87581.js.map
  66. 0 0
      src/static/js/335.274bb63c.js
  67. 0 0
      src/static/js/335.274bb63c.js.map
  68. 0 0
      src/static/js/335.49ff737f.js
  69. 0 0
      src/static/js/335.49ff737f.js.map
  70. 0 0
      src/static/js/335.79b18870.js
  71. 0 0
      src/static/js/335.79b18870.js.map
  72. 0 0
      src/static/js/460.25c3593f.js
  73. 0 0
      src/static/js/460.25c3593f.js.map
  74. 0 0
      src/static/js/460.748246c0.js
  75. 0 0
      src/static/js/460.748246c0.js.map
  76. 0 0
      src/static/js/47.ef20937f.js
  77. 0 0
      src/static/js/47.ef20937f.js.map
  78. 0 0
      src/static/js/493.0351ca68.js
  79. 0 0
      src/static/js/493.0351ca68.js.map
  80. 0 0
      src/static/js/493.638f7506.js
  81. 0 0
      src/static/js/493.638f7506.js.map
  82. 0 0
      src/static/js/533.5b28713a.js
  83. 0 0
      src/static/js/533.5b28713a.js.map
  84. 0 0
      src/static/js/533.ff7f86df.js
  85. 0 0
      src/static/js/533.ff7f86df.js.map
  86. 0 0
      src/static/js/64.3506c92c.js
  87. 0 0
      src/static/js/64.3506c92c.js.map
  88. 0 0
      src/static/js/64.45bd4d08.js
  89. 0 0
      src/static/js/64.45bd4d08.js.map
  90. 0 0
      src/static/js/641.25ad542f.js
  91. 0 0
      src/static/js/641.25ad542f.js.map
  92. 0 0
      src/static/js/641.47532478.js
  93. 0 0
      src/static/js/641.47532478.js.map
  94. 0 0
      src/static/js/664.3719fbae.js
  95. 0 0
      src/static/js/664.3719fbae.js.map
  96. 0 0
      src/static/js/705.6cf720bc.js
  97. 0 0
      src/static/js/705.6cf720bc.js.map
  98. 0 0
      src/static/js/705.9267a874.js
  99. 0 0
      src/static/js/705.9267a874.js.map
  100. 0 0
      src/static/js/759.66f7f960.js

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+src/bin/

+ 0 - 3
.gitmodules

@@ -1,3 +0,0 @@
-[submodule "comm"]
-	path = comm
-	url = http://124.70.149.18:10880/service/comm.git

+ 156 - 0
src/api/admin.go

@@ -0,0 +1,156 @@
+package api
+
+import (
+	"cmf/db/model"
+	"cmf/db/repo"
+	"time"
+
+	"github.com/gin-gonic/gin"
+	"go.mongodb.org/mongo-driver/bson/primitive"
+	"golang.org/x/crypto/bcrypt"
+)
+
+// HashPassword creates a bcrypt hash of the password
+func HashPassword(password string) (string, error) {
+	bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
+	return string(bytes), err
+}
+
+// CheckPasswordHash compares a password with a hash
+func CheckPasswordHash(password, hash string) bool {
+	err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
+	return err == nil
+}
+
+func AdminLogin(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	// Get login credentials from request
+	var loginReq struct {
+		Phone    string `json:"phone"`
+		Password string `json:"password"`
+	}
+
+	if err := c.ShouldBindJSON(&loginReq); err != nil {
+		return nil, err
+	}
+
+	// Check if admin users collection exists and has any users
+	// If not, create a default admin user
+	ensureDefaultAdmin(apictx)
+
+	// Query the database for the user with the provided phone number
+	var user model.User
+	repoCtx := apictx.CreateRepoCtx()
+	found, err := repo.RepoSeachDoc(repoCtx, &repo.DocSearchOptions{
+		CollectName: "admin_users",
+		Query:       repo.Map{"phone": loginReq.Phone},
+	}, &user)
+
+	if err != nil {
+		return nil, err
+	}
+
+	if !found {
+		return nil, NewError("账号密码错误")
+	}
+
+	// Verify password
+	if !CheckPasswordHash(loginReq.Password, user.Password) {
+		return nil, NewError("账号密码错误")
+	}
+
+	// Create a user object for the JWT token
+	jwtUser := &JWTUser{
+		Id:       user.Id.Hex(),
+		Name:     user.Name,
+		Phone:    user.Phone,
+		Role:     "admin",
+		State:    1,
+		UserType: 1,
+	}
+
+	// Generate JWT token
+	token, expire, err := apictx.Svc.JWT.JwtCreateToken(jwtUser)
+	if err != nil {
+		return nil, err
+	}
+
+	// Return token and user info
+	return map[string]interface{}{
+		"token":  token,
+		"expire": expire.Format("2006-01-02T15:04:05Z07:00"),
+	}, nil
+}
+
+func ensureDefaultAdmin(apictx *ApiSession) error {
+	repoCtx := apictx.CreateRepoCtx()
+
+	// Check if admin_users collection has any documents
+	count, err := repo.RepoCountDoc(repoCtx, "admin_users", repo.Map{})
+	if err != nil {
+		return err
+	}
+
+	// If no admin users exist, create a default one
+	if count == 0 {
+		// Hash the default password
+		hashedPassword, err := HashPassword("123456")
+		if err != nil {
+			return err
+		}
+
+		// Create default admin user
+		defaultAdmin := model.User{
+			Id:         primitive.NewObjectID(),
+			LoginName:  "admin",
+			Phone:      "admin",
+			Password:   hashedPassword,
+			Name:       "Admin",
+			Email:      "admin@example.com",
+			CreateTime: time.Now(),
+			UpdateTime: time.Now(),
+			UserType:   func() *int { i := 1; return &i }(),
+		}
+		_, err = repo.RepoAddDoc(repoCtx, "admin_users", &defaultAdmin)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+// GetAdminUserInfo retrieves the current admin user's information
+func GetAdminUserInfo(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	// Check if user is authenticated
+	if apictx.User == nil {
+		return nil, NewError("User not authenticated")
+	}
+
+	// Get user ID from JWT token
+	userId, err := primitive.ObjectIDFromHex(apictx.User.Id)
+	if err != nil {
+		return nil, NewError("Invalid user ID")
+	}
+
+	// Query the database for the user
+	var user model.User
+	repoCtx := apictx.CreateRepoCtx()
+	found, err := repo.RepoSeachDoc(repoCtx, &repo.DocSearchOptions{
+		CollectName: "admin_users",
+		Query:       repo.Map{"_id": userId},
+	}, &user)
+
+	if err != nil {
+		return nil, err
+	}
+
+	if !found {
+		return nil, NewError("User not found")
+	}
+
+	// Remove sensitive information
+	user.Password = ""
+
+	// Return user information
+	return user, nil
+}

+ 27 - 19
src/api/api.go

@@ -4,7 +4,6 @@ import (
 	"cmf/conf"
 	"cmf/db"
 	"cmf/db/repo"
-	"cmf/middleware"
 	"context"
 	"fmt"
 	"os"
@@ -16,15 +15,15 @@ import (
 )
 
 type Service struct {
-	Gin   *gin.Engine
-	Mongo *db.MongoDB
-	Redis *redis.Client
-	Port  int32
-	// DebugUserId    string
-	// DebugUserPhone string
-	// DebugUserRole  string
-	// JWT            *UtilsJwt
-	Conf *conf.AppConf
+	Gin            *gin.Engine
+	Mongo          *db.MongoDB
+	Redis          *redis.Client
+	Port           int32
+	DebugUserId    string
+	DebugUserPhone string
+	DebugUserRole  string
+	JWT            *UtilsJwt
+	Conf           *conf.AppConf
 }
 
 func (svc *Service) Run() {
@@ -32,9 +31,9 @@ func (svc *Service) Run() {
 }
 
 type ApiSession struct {
-	Svc *Service
-	// User *JWTUser
-	User *casdoorsdk.Claims
+	Svc  *Service
+	User *JWTUser
+	// User *casdoorsdk.Claims
 }
 
 func (api *ApiSession) CreateRepoCtx() *repo.RepoSession {
@@ -55,6 +54,9 @@ func NewHttpService(app *conf.AppConf, dbMongo *db.MongoDB) *Service {
 
 	engine := gin.Default()
 
+	// 配置静态文件服务
+	engine.Static("/static", "./static")
+
 	// store := cookie.NewStore([]byte("spu3d-server"))
 	// engine.Use(sessions.Sessions("dcsession", store))
 	// engine.Static("/public", "static")
@@ -64,7 +66,9 @@ func NewHttpService(app *conf.AppConf, dbMongo *db.MongoDB) *Service {
 	config.AllowHeaders = append(config.AllowHeaders, "authorization")
 	engine.Use(cors.New(config))
 
-	s := &Service{Conf: app, Gin: engine, Mongo: dbMongo, Port: app.Port}
+	jwt := NewUitlsJwt(app)
+
+	s := &Service{Conf: app, Gin: engine, JWT: jwt, Mongo: dbMongo, Port: app.Port}
 
 	RegRouters(s)
 
@@ -99,15 +103,19 @@ func (g GinRouter) POST(path string, httpHandler Handler) {
 
 // GETJWT http Get 请求
 func (g GinRouter) GETJWT(path string, httpHandler JWTHander) {
-	g.group.GET(path, middleware.CasdoorAuthMiddleware(), ResultJWTWrapper(httpHandler, g.svc))
+	g.group.GET(path, g.svc.JWT.MiddleFunc(), ResultJWTWrapper(httpHandler, g.svc))
 }
 
 // POSTJWT http POST 请求
 func (g GinRouter) POSTJWT(path string, httpHandler JWTHander) {
-	g.group.POST(path, middleware.CasdoorAuthMiddleware(), ResultJWTWrapper(httpHandler, g.svc))
+	g.group.POST(path, g.svc.JWT.MiddleFunc(), ResultJWTWrapper(httpHandler, g.svc))
 }
 
-// DeleteJWT http POST 请求
-func (g GinRouter) DeleteJWT(path string, httpHandler JWTHander) {
-	g.group.DELETE(path, middleware.CasdoorAuthMiddleware(), ResultJWTWrapper(httpHandler, g.svc))
+var miniAppAllowKey = []string{"client"}
+
+func (g GinRouter) GETJWTCLIENT(path string, httpHandler JWTHander) {
+	g.group.GET(path, g.svc.JWT.MiddleFunc(), ResultJWTWrapperKey(httpHandler, g.svc, miniAppAllowKey))
+}
+func (g GinRouter) POSTJWTCLIENT(path string, httpHandler JWTHander) {
+	g.group.POST(path, g.svc.JWT.MiddleFunc(), ResultJWTWrapperKey(httpHandler, g.svc, miniAppAllowKey))
 }

+ 0 - 31
src/api/callback.go

@@ -1,31 +0,0 @@
-package api
-
-import (
-	"fmt"
-
-	"github.com/casdoor/casdoor-go-sdk/casdoorsdk"
-	"github.com/gin-gonic/gin"
-)
-
-// https://auth.3dqueen.cloud/login/oauth/authorize?client_id=d372dce9cd00805db7e0&redirect_uri=http://localhost:9999/cmf/login/callback&response_type=code&scope=openid&state=STATE
-// 需要在第三方提供商配置回调 https://auth.3dqueen.cloud/callback
-func callback(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-
-	token, err := casdoorsdk.GetOAuthToken(c.Query("code"), c.Query("state"))
-	if err != nil {
-		fmt.Println(err)
-		return err, nil
-	}
-
-	fmt.Println(token.AccessToken)
-	claims, err := casdoorsdk.ParseJwtToken(token.AccessToken)
-	if err != nil {
-		fmt.Println(err)
-		return err, nil
-	}
-	fmt.Println(claims)
-	// c.Redirect(http.StatusFound, "https://auth.3dqueen.cloud")
-
-	claims.AccessToken = token.AccessToken
-	return claims, nil
-}

+ 2 - 2
src/api/case.go

@@ -41,7 +41,7 @@ func CreateMyMat(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	data.CreateTime = time.Now()
 	data.UpdateTime = time.Now()
 	data.UserId = apictx.User.Id
-	data.UserName = apictx.User.DisplayName
+	data.UserName = apictx.User.Name
 	return repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionMyMat, &data)
 }
 
@@ -56,7 +56,7 @@ func CreateMyCase(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	obj.CreateTime = time.Now()
 	obj.UpdateTime = time.Now()
 	obj.UserId = apictx.User.Id
-	obj.UserName = apictx.User.DisplayName
+	obj.UserName = apictx.User.Name
 
 	return repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionMyCase, &obj)
 }

+ 1 - 1
src/api/category.go

@@ -63,7 +63,7 @@ func defUpdateCategory(router *GinRouter, path string, catType string) {
 		body := &comm.DbCategory{}
 		err := c.ShouldBindJSON(body)
 		if err != nil {
-			PrintErr(err, "参数错误")
+			// PrintErr(err, "参数错误")
 			return nil, errors.New("参数错误!")
 		}
 		body.Scope = catType

+ 143 - 0
src/api/client.go

@@ -0,0 +1,143 @@
+package api
+
+import (
+	"cmf/db/model"
+	"cmf/db/repo"
+	"time"
+
+	"github.com/gin-gonic/gin"
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+func ClientLogin(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	// Get login credentials from request
+	var loginReq struct {
+		Phone    string `json:"phone"`
+		Password string `json:"password"`
+	}
+
+	if err := c.ShouldBindJSON(&loginReq); err != nil {
+		return nil, err
+	}
+
+	// Check if admin users collection exists and has any users
+	// If not, create a default admin user
+	ensureDefaultClient(apictx)
+
+	// Query the database for the user with the provided phone number
+	var user model.User
+	repoCtx := apictx.CreateRepoCtx()
+	found, err := repo.RepoSeachDoc(repoCtx, &repo.DocSearchOptions{
+		CollectName: "client_users",
+		Query:       repo.Map{"phone": loginReq.Phone},
+	}, &user)
+
+	if err != nil {
+		return nil, err
+	}
+
+	if !found {
+		return nil, NewError("账号密码错误")
+	}
+
+	// Verify password
+	if !CheckPasswordHash(loginReq.Password, user.Password) {
+		return nil, NewError("账号密码错误")
+	}
+
+	// Create a user object for the JWT token
+	jwtUser := &JWTUser{
+		Id:       user.Id.Hex(),
+		Name:     user.Name,
+		Phone:    user.Phone,
+		Role:     "client",
+		Key:      "client",
+		State:    1,
+		UserType: 1,
+	}
+
+	// Generate JWT token
+	token, expire, err := apictx.Svc.JWT.JwtCreateToken(jwtUser)
+	if err != nil {
+		return nil, err
+	}
+
+	// Return token and user info
+	return map[string]interface{}{
+		"token":  token,
+		"expire": expire.Format("2006-01-02T15:04:05Z07:00"),
+	}, nil
+}
+
+func ensureDefaultClient(apictx *ApiSession) error {
+	repoCtx := apictx.CreateRepoCtx()
+
+	// Check if admin_users collection has any documents
+	count, err := repo.RepoCountDoc(repoCtx, "client_users", repo.Map{})
+	if err != nil {
+		return err
+	}
+
+	// If no admin users exist, create a default one
+	if count == 0 {
+		// Hash the default password
+		hashedPassword, err := HashPassword("123456")
+		if err != nil {
+			return err
+		}
+
+		// Create default admin user
+		defaultAdmin := model.User{
+			Id:         primitive.NewObjectID(),
+			LoginName:  "client",
+			Phone:      "client",
+			Password:   hashedPassword,
+			Name:       "Client",
+			Email:      "admin@example.com",
+			CreateTime: time.Now(),
+			UpdateTime: time.Now(),
+			UserType:   func() *int { i := 1; return &i }(),
+		}
+		_, err = repo.RepoAddDoc(repoCtx, "client_users", &defaultAdmin)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+// GetAdminUserInfo retrieves the current admin user's information
+func GetClientUserInfo(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	// Check if user is authenticated
+	if apictx.User == nil {
+		return nil, NewError("User not authenticated")
+	}
+
+	// Get user ID from JWT token
+	userId, err := primitive.ObjectIDFromHex(apictx.User.Id)
+	if err != nil {
+		return nil, NewError("Invalid user ID")
+	}
+
+	// Query the database for the user
+	var user model.User
+	repoCtx := apictx.CreateRepoCtx()
+	found, err := repo.RepoSeachDoc(repoCtx, &repo.DocSearchOptions{
+		CollectName: "client_users",
+		Query:       repo.Map{"_id": userId},
+	}, &user)
+
+	if err != nil {
+		return nil, err
+	}
+
+	if !found {
+		return nil, NewError("User not found")
+	}
+	// Remove sensitive information
+	user.Password = ""
+
+	// Return user information
+	return user, nil
+}

+ 190 - 49
src/api/controller.go

@@ -4,15 +4,15 @@ import (
 	"cmf/log"
 	"crypto/md5"
 	"encoding/json"
-	"errors"
 	"fmt"
 	"net/http"
 	"runtime"
 	"strconv"
 	"strings"
 
-	"github.com/casdoor/casdoor-go-sdk/casdoorsdk"
+	jwt "github.com/appleboy/gin-jwt/v2"
 	"github.com/gin-gonic/gin"
+	"go.mongodb.org/mongo-driver/bson/primitive"
 )
 
 // Handler 包装http处理函数
@@ -75,14 +75,115 @@ func ResultJWTWrapper(handle JWTHander, svc *Service) gin.HandlerFunc {
 			}
 		}()
 
-		claims, _ := c.Get("casdoor_user")
+		claims := jwt.ExtractClaims(c)
 
-		user := claims.(*casdoorsdk.Claims)
+		var usr *JWTUser
+
+		if claims["id"] != nil {
+			id := claims["id"].(string)
+			phone := claims["phone"].(string)
+			parent := claims["parent"].(string)
+
+			OpenId := ""
+			if claims["openId"] != nil {
+				OpenId = claims["openId"].(string)
+			}
+
+			state := int32(claims["state"].(float64))
+			key := ""
+			if claims["key"] != nil {
+				key = claims["key"].(string)
+			}
+			name := ""
+			if claims["name"] != nil {
+				name = claims["name"].(string)
+			}
+
+			usr = &JWTUser{OpenId: OpenId, Id: id, Name: name, Phone: phone, Parent: parent, State: state, Key: key}
+		}
+
+		var apis = &ApiSession{
+			Svc:  svc,
+			User: usr,
+		}
+
+		data, err := handle(c, apis)
+
+		if err != nil {
+			fmt.Println(err)
+			httpErr, ok := err.(HTTPError)
+			if ok {
+				c.JSON(http.StatusOK, NewFailResultWithCode(httpErr.Error(), httpErr.Code))
+				return
+			}
+
+			c.JSON(http.StatusOK, NewFailResult(err.Error()))
+			return
+		}
+		if data != nil {
+			c.JSON(http.StatusOK, NewOkResult(data))
+		}
+	}
+}
+
+// ResultJWTWrapper JWT授权处理handler
+func ResultJWTWrapperKey(handle JWTHander, svc *Service, keys []string) gin.HandlerFunc {
+
+	return func(c *gin.Context) {
+
+		defer func() {
+			if r := recover(); r != nil {
+				fmt.Println("recover success.")
+				fmt.Println(r)
+
+				buf := make([]byte, 1<<16)
+				runtime.Stack(buf, true)
+				fmt.Println("buf", string(buf))
+
+				c.JSON(http.StatusOK, NewFailResultWithData("系统异常", r))
+			}
+		}()
+
+		claims := jwt.ExtractClaims(c)
+
+		var usr *JWTUser
+
+		if claims["id"] != nil {
+			id := claims["id"].(string)
+			phone := claims["phone"].(string)
+			name := claims["name"].(string)
+			parent := claims["parent"].(string)
+			openId := ""
+			if claims["openId"] != nil {
+				openId = claims["openId"].(string)
+			}
+			state := int32(claims["state"].(float64))
+			key := ""
+			if claims["key"] != nil {
+				key = claims["key"].(string)
+			}
+
+			usr = &JWTUser{OpenId: openId, Id: id, Name: name, Phone: phone, Parent: parent, State: state, Key: key}
+		}
 
 		var apis = &ApiSession{
 			Svc:  svc,
-			User: user,
+			User: usr,
+		}
+
+		flag := false
+		for _, key := range keys {
+			if usr.Key == key {
+				flag = true
+				break
+			}
+		}
+		if !flag {
+			c.JSON(http.StatusForbidden, NewFailResult("您没有权限"))
+			c.Abort()
+			return
 		}
+
 		data, err := handle(c, apis)
 
 		if err != nil {
@@ -102,6 +203,44 @@ func ResultJWTWrapper(handle JWTHander, svc *Service) gin.HandlerFunc {
 	}
 }
 
+// ResultJWTTestWrapper test 默认一个测试用户 JWT授权处理handler
+func ResultJWTTestWrapper(handle JWTHander, svc *Service) gin.HandlerFunc {
+
+	return func(c *gin.Context) {
+
+		defer func() {
+			if r := recover(); r != nil {
+
+				fmt.Println("recover success.")
+				fmt.Println(r)
+
+				buf := make([]byte, 1<<16)
+				runtime.Stack(buf, true)
+				fmt.Println("buf", string(buf))
+
+				c.JSON(http.StatusOK, NewFailResultWithData("error", r))
+			}
+		}()
+
+		var usr *JWTUser = &JWTUser{Id: svc.DebugUserId, Phone: svc.DebugUserPhone, Parent: svc.DebugUserId, Role: svc.DebugUserRole}
+
+		data, err := handle(c, &ApiSession{Svc: svc, User: usr})
+
+		if err != nil {
+			fmt.Println(err)
+			httpErr, ok := err.(HTTPError)
+			if ok {
+				c.JSON(http.StatusOK, NewFailResultWithCode(httpErr.Error(), httpErr.Code))
+				return
+			}
+
+			c.JSON(http.StatusOK, NewFailResult(err.Error()))
+			return
+		}
+		c.JSON(http.StatusOK, NewOkResult(data))
+	}
+}
+
 // ResultSuc 成功
 func ResultSuc(c *gin.Context, data interface{}) {
 	c.JSON(http.StatusOK, NewOkResult(data))
@@ -130,32 +269,43 @@ func UtilQueryPageSize(c *gin.Context) (page int64, size int64, query map[string
 	s := c.Query("size")
 	q := c.Query("query")
 
-	var _page = 1
-
-	if len(p) > 0 {
-		_page, _ = strconv.Atoi(p)
-	}
-	page = int64(_page)
-
-	var _size = 10
-	if len(s) > 0 {
-		_size, _ = strconv.Atoi(s)
+	result := make(map[string]interface{})
+	if len(q) > 0 {
+		// 使用 json.Unmarshal 解析 JSON 字符串
+		json.Unmarshal([]byte(q), &result)
 	}
-	size = int64(_size)
-	query = make(map[string]interface{})
-
-	if len(q) > 0 && q != "{}" {
-		json.Unmarshal([]byte(q), &query)
+	params := c.Request.URL.Query()
+	// 遍历所有参数
+	for key, values := range params {
+		// 检查是否以 "query[" 开头且格式正确
+		if strings.HasPrefix(key, "query[") && strings.HasSuffix(key, "]") {
+			// 提取字段名(如 "isAdmin")
+			field := key[len("query[") : len(key)-1]
+
+			if len(values) == 0 {
+				continue
+			}
+			valueStr := values[0]
+
+			// 类型推断逻辑
+			var value interface{}
+			switch strings.ToLower(valueStr) {
+			case "true":
+				value = true
+			case "false":
+				value = false
+			default:
+				if intVal, err := strconv.Atoi(valueStr); err == nil {
+					value = intVal
+				} else if floatVal, err := strconv.ParseFloat(valueStr, 64); err == nil {
+					value = floatVal
+				} else {
+					value = valueStr
+				}
+			}
+			result[field] = value
+		}
 	}
-	return
-}
-
-func UtilQueryPageSize2(c *gin.Context) (page int64, size int64, query map[string]interface{}, fields []string) {
-	p := c.Query("page")
-	s := c.Query("size")
-	q := c.Query("query")
-	f := c.Query("fields")
-
 	var _page = 1
 
 	if len(p) > 0 {
@@ -168,17 +318,8 @@ func UtilQueryPageSize2(c *gin.Context) (page int64, size int64, query map[strin
 		_size, _ = strconv.Atoi(s)
 	}
 	size = int64(_size)
+	query = result
 
-	if len(q) > 0 {
-		json.Unmarshal([]byte(q), &query)
-	} else {
-		query = map[string]interface{}{}
-	}
-	if len(f) > 0 {
-		fields = strings.Split(f, ",")
-	} else {
-		fields = []string{}
-	}
 	return
 }
 
@@ -247,18 +388,10 @@ func NewErrorWithCode(desc string, code int32) HTTPError {
 	return HTTPError{Code: code, Message: desc}
 }
 
-func PrintErr(err error, desc string) (interface{}, error) {
-	_, file, line, _ := runtime.Caller(1)
-	log.Errorf("错误文件:%s错误位置:%d 错误信息:%s\n", file, line, err.Error())
-	fmt.Println(">err--------------------------------------------------err<")
-	fmt.Println("[error]:", desc, err)
-	fmt.Println("<err--------------------------------------------------err>")
-	return nil, errors.New(desc)
-}
-
 // JWTUser jwt登录用户
 type JWTUser struct {
-	ID       string `json:"id"`
+	Id       string `json:"id"`
+	OpenId   string `json:"openId"`
 	Parent   string `json:"parent"`
 	Name     string `json:"name"`
 	Phone    string `json:"phone"`
@@ -269,6 +402,11 @@ type JWTUser struct {
 	UserType int    `json:"userType"`
 }
 
+func (u JWTUser) ObjectID() primitive.ObjectID {
+	uid, _ := primitive.ObjectIDFromHex(u.Id)
+	return uid
+}
+
 func UtilQueryMap(c *gin.Context) map[string]interface{} {
 	query := map[string]interface{}{}
 	q := c.Query("query")
@@ -284,6 +422,9 @@ func BoolValue(value bool) *bool {
 func Int32Value(value int32) *int32 {
 	return &value
 }
+func IntValue(value int) *int {
+	return &value
+}
 func Float32Value(value float32) *float32 {
 	return &value
 }

+ 172 - 0
src/api/jwt.go

@@ -0,0 +1,172 @@
+package api
+
+import (
+	"cmf/conf"
+	"fmt"
+	"log"
+	"time"
+
+	jwt "github.com/appleboy/gin-jwt/v2"
+	"github.com/gin-gonic/gin"
+)
+
+var identityKey = "id"
+
+type UtilsJwt struct {
+	jwt *jwt.GinJWTMiddleware
+}
+
+func (j *UtilsJwt) MiddleFunc() gin.HandlerFunc {
+	return j.jwt.MiddlewareFunc()
+}
+
+func (j *UtilsJwt) JwtCreateToken(data interface{}) (string, time.Time, error) {
+	return j.jwt.TokenGenerator(data)
+}
+
+func NewUitlsJwt(app *conf.AppConf) *UtilsJwt {
+
+	var utils = &UtilsJwt{
+		jwt: nil,
+	}
+
+	var jwtImpl *jwt.GinJWTMiddleware
+
+	jwtImpl, err := jwt.New(&jwt.GinJWTMiddleware{
+		Realm:       app.Jwt.Realm,
+		Key:         []byte(app.Jwt.Key),
+		Timeout:     time.Hour * time.Duration(app.Jwt.TimeoutHour),
+		MaxRefresh:  time.Hour * time.Duration(app.Jwt.TimeoutHour),
+		IdentityKey: identityKey,
+		PayloadFunc: func(data interface{}) jwt.MapClaims {
+			if v, ok := data.(*JWTUser); ok {
+				return jwt.MapClaims{
+					"id":       v.Id,
+					"name":     v.Name,
+					"phone":    v.Phone,
+					"openId":   v.OpenId,
+					"role":     v.Role,
+					"parent":   v.Parent,
+					"state":    v.State,
+					"key":      v.Key,
+					"userType": v.UserType,
+				}
+			}
+			return jwt.MapClaims{}
+		},
+		IdentityHandler: func(c *gin.Context) interface{} {
+			claims := jwt.ExtractClaims(c)
+			// lg.Debug().Msgf("token: %v\n", claims)
+
+			u := &JWTUser{
+				Id:     claims["id"].(string), //uint32(claims["id"].(float64)),
+				Phone:  claims["phone"].(string),
+				Parent: claims["parent"].(string),
+			}
+			if claims["key"] != nil {
+				u.Key = claims["key"].(string)
+			}
+			if claims["name"] != nil {
+				u.Name = claims["name"].(string)
+			}
+			if claims["state"] != nil {
+				u.State = int32(claims["state"].(float64))
+			}
+			if claims["userType"] != nil {
+				u.UserType = int(claims["userType"].(float64))
+			}
+			if claims["openId"] != nil {
+				u.OpenId = claims["openId"].(string)
+			}
+			return u
+		},
+
+		Authenticator: func(c *gin.Context) (interface{}, error) {
+			return &JWTUser{Phone: "empty"}, nil
+		},
+
+		Authorizator: func(data interface{}, _ *gin.Context) bool {
+			u := data.(*JWTUser)
+
+			return u.State > 0
+		},
+
+		LoginResponse: func(c *gin.Context, status int, token string, expire time.Time) {
+
+			t, _ := jwtImpl.ParseTokenString(token)
+			fmt.Println("LoginResponse==>", status, token)
+
+			ResultSuc(c, map[string]interface{}{
+				"user":   t.Claims,
+				"token":  token,
+				"expire": expire.Format(time.RFC3339),
+			})
+		},
+
+		LogoutResponse: func(c *gin.Context, _ int) {
+			ResultSuc(c, true)
+		},
+
+		RefreshResponse: func(c *gin.Context, status int, token string, expire time.Time) {
+
+			ResultSuc(c, map[string]interface{}{
+				"status": status,
+				"token":  token,
+				"expire": expire.Format(time.RFC3339),
+			})
+		},
+
+		Unauthorized: func(c *gin.Context, status int, token string) {
+			if token == "用户名/密码 不正确" {
+				ResultFail401(c, "账号密码不对", map[string]interface{}{
+					"status": -1,
+					"token":  token,
+				})
+				return
+			}
+
+			fmt.Println("xxxxx")
+			fmt.Println(token, status)
+
+			ResultFail401(c, token, map[string]interface{}{
+				"status": status,
+				"token":  token,
+			})
+		},
+
+		HTTPStatusMessageFunc: func(e error, _ *gin.Context) string {
+
+			// if e == jwt.ErrFailedAuthentication {
+			// 	return "用户名/密码 不正确"
+			// }
+			fmt.Println("HTTPStatusMessageFunc", e)
+			return e.Error()
+		},
+
+		// TokenLookup is a string in the form of "<source>:<name>" that is used
+		// to extract token from the request.
+		// Optional. Default value "header:Authorization".
+		// Possible values:
+		// - "header:<name>"
+		// - "query:<name>"
+		// - "cookie:<name>"
+		// - "param:<name>"
+		TokenLookup: "header: Authorization, query: token, cookie: jwt",
+		// TokenLookup: "query:token",
+		// TokenLookup: "cookie:token",
+
+		// TokenHeadName is a string in the header. Default value is "Bearer"
+		TokenHeadName: "Bearer",
+
+		// TimeFunc provides the current time. You can override it to use another time value. This is useful for testing or if your server uses a different time zone than your tokens.
+		TimeFunc: time.Now,
+	})
+
+	if err != nil {
+		log.Fatal("JWT Error:" + err.Error())
+	}
+
+	utils.jwt = jwtImpl
+
+	return utils
+}

+ 11 - 1
src/api/router.go

@@ -12,6 +12,10 @@ func RegRouters(svc *Service) {
 	r := svc.NewGinRouter("/cmf")
 
 	r.group.Use(Logger())
+
+	// 注册文件上传路由
+	Upload(r)
+
 	// website := r.group.Group("/website")
 
 	// // nav
@@ -30,7 +34,13 @@ func RegRouters(svc *Service) {
 	// r.POSTJWT("/gallery/update", UpdateGallery)
 
 	// category
-	r.GET("/getToken", callback)
+	// r.GET("/getToken", callback)
+	r.POST("/admin/login", AdminLogin)
+	r.GETJWT("/admin/userinfo", GetAdminUserInfo)
+
+	r.POST("/client/login", ClientLogin)
+	r.GETJWTCLIENT("/client/userinfo", GetClientUserInfo)
+
 	r.GETJWT("/r1", func(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 		return apictx.User, nil
 	})

+ 50 - 0
src/api/upload.go

@@ -0,0 +1,50 @@
+package api
+
+import (
+	"cmf/log"
+	"errors"
+	"fmt"
+	"os"
+	"path/filepath"
+	"time"
+
+	"github.com/gin-gonic/gin"
+)
+
+func Upload(r *GinRouter) {
+	r.POST("/upload", UploadFile)
+}
+
+func UploadFile(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	// 获取上传的文件
+	file, err := c.FormFile("file")
+	if err != nil {
+		log.Error(err)
+		return nil, errors.New("获取上传文件失败")
+	}
+
+	// 确保上传目录存在
+	uploadDir := "static/uploads"
+	if err := os.MkdirAll(uploadDir, 0755); err != nil {
+		log.Error(err)
+		return nil, errors.New("创建上传目录失败")
+	}
+
+	// 生成唯一文件名,避免文件名冲突
+	filename := fmt.Sprintf("%d_%s", time.Now().UnixNano(), file.Filename)
+	filepath := filepath.Join(uploadDir, filename)
+
+	// 保存文件
+	if err := c.SaveUploadedFile(file, filepath); err != nil {
+		log.Error(err)
+		return nil, errors.New("保存文件失败")
+	}
+
+	// 返回文件信息
+	return map[string]interface{}{
+		"filename": filename,
+		"path":     filepath,
+		"url":      "/static/uploads/" + filename,
+		"size":     file.Size,
+	}, nil
+}

+ 2 - 5
src/db/db.go

@@ -36,15 +36,12 @@ func (db *MongoDB) GetOrCreateDatabase(name string) *mongo.Database {
 	return datab
 }
 
-func NewMongoDB(bus *comm.NatsBus) *MongoDB {
-
-	inst, err := bus.NewMongoDBFromConfig("cmf-mongo")
-
+func NewMongoDB() *MongoDB {
+	inst, err := comm.CreateMongo("mongodb://root:cmfxxx@localhost:27017/cmf?authSource=admin")
 	if err != nil {
 		fmt.Println(err)
 		panic(err)
 	}
-
 	MongoClient = &MongoDB{Client: inst.Client, Database: inst.Database, Databases: map[string]*mongo.Database{}}
 	return MongoClient
 }

+ 31 - 21
src/go.mod

@@ -1,11 +1,14 @@
 module cmf
 
-go 1.20
+go 1.23.0
+
+toolchain go1.23.8
 
 require (
+	github.com/appleboy/gin-jwt/v2 v2.10.3
 	github.com/casdoor/casdoor-go-sdk v1.3.0
 	github.com/gin-contrib/cors v1.3.1
-	github.com/gin-gonic/gin v1.7.4
+	github.com/gin-gonic/gin v1.10.0
 	github.com/go-redis/redis/v8 v8.11.5
 	github.com/natefinch/lumberjack v2.0.0+incompatible
 	github.com/spf13/viper v1.9.0
@@ -15,23 +18,25 @@ require (
 	infish.cn/comm v0.0.0
 )
 
-require (
-	github.com/nats-io/nats.go v1.22.1 // indirect
-	github.com/stretchr/testify v1.8.4 // indirect
-)
+require github.com/nats-io/nats.go v1.22.1 // indirect
 
 require (
 	github.com/StackExchange/wmi v1.2.1 // indirect
+	github.com/bytedance/sonic v1.12.9 // indirect
+	github.com/bytedance/sonic/loader v0.2.3 // indirect
 	github.com/cenkalti/backoff/v4 v4.2.0 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
+	github.com/cloudwego/base64x v0.1.5 // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 	github.com/fsnotify/fsnotify v1.5.1 // indirect
-	github.com/gin-contrib/sse v0.1.0 // indirect
+	github.com/gabriel-vasile/mimetype v1.4.8 // indirect
+	github.com/gin-contrib/sse v1.0.0 // indirect
 	github.com/go-ole/go-ole v1.2.5 // indirect
-	github.com/go-playground/locales v0.13.0 // indirect
-	github.com/go-playground/universal-translator v0.17.0 // indirect
-	github.com/go-playground/validator/v10 v10.4.1 // indirect
-	github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
+	github.com/go-playground/locales v0.14.1 // indirect
+	github.com/go-playground/universal-translator v0.18.1 // indirect
+	github.com/go-playground/validator/v10 v10.25.0 // indirect
+	github.com/goccy/go-json v0.10.5 // indirect
+	github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
 	github.com/golang-migrate/migrate/v4 v4.15.2 // indirect
 	github.com/golang/protobuf v1.5.3 // indirect
 	github.com/golang/snappy v0.0.4 // indirect
@@ -42,9 +47,10 @@ require (
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
 	github.com/klauspost/compress v1.15.13 // indirect
-	github.com/leodido/go-urn v1.2.0 // indirect
+	github.com/klauspost/cpuid/v2 v2.2.9 // indirect
+	github.com/leodido/go-urn v1.4.0 // indirect
 	github.com/magiconair/properties v1.8.5 // indirect
-	github.com/mattn/go-isatty v0.0.12 // indirect
+	github.com/mattn/go-isatty v0.0.20 // indirect
 	github.com/minio/highwayhash v1.0.2 // indirect
 	github.com/mitchellh/mapstructure v1.4.2 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
@@ -54,29 +60,33 @@ require (
 	github.com/nats-io/nkeys v0.3.0 // indirect
 	github.com/nats-io/nuid v1.0.1 // indirect
 	github.com/pelletier/go-toml v1.9.4 // indirect
+	github.com/pelletier/go-toml/v2 v2.2.3 // indirect
 	github.com/sirupsen/logrus v1.9.0 // indirect
 	github.com/spf13/afero v1.6.0 // indirect
 	github.com/spf13/cast v1.4.1 // indirect
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/subosito/gotenv v1.2.0 // indirect
-	github.com/ugorji/go/codec v1.1.7 // indirect
+	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+	github.com/ugorji/go/codec v1.2.12 // indirect
 	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
 	github.com/xdg-go/scram v1.1.2 // indirect
 	github.com/xdg-go/stringprep v1.0.4 // indirect
-	github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
+	github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
 	go.uber.org/atomic v1.10.0 // indirect
 	go.uber.org/multierr v1.6.0 // indirect
-	golang.org/x/crypto v0.14.0 // indirect
-	golang.org/x/net v0.16.0 // indirect
+	golang.org/x/arch v0.14.0 // indirect
+	golang.org/x/crypto v0.36.0 // indirect
+	golang.org/x/net v0.37.0 // indirect
 	golang.org/x/oauth2 v0.13.0 // indirect
-	golang.org/x/sync v0.1.0 // indirect
-	golang.org/x/sys v0.13.0 // indirect
-	golang.org/x/text v0.13.0 // indirect
+	golang.org/x/sync v0.12.0 // indirect
+	golang.org/x/sys v0.31.0 // indirect
+	golang.org/x/text v0.23.0 // indirect
 	google.golang.org/appengine v1.6.7 // indirect
-	google.golang.org/protobuf v1.31.0 // indirect
+	google.golang.org/protobuf v1.36.5 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
 
 replace infish.cn/comm => ../comm

+ 88 - 35
src/go.sum

@@ -122,6 +122,10 @@ github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/apache/arrow/go/arrow v0.0.0-20210818145353-234c94e4ce64/go.mod h1:2qMFB56yOP3KzkB3PbYZ4AlUFg3a88F67TIx5lB/WwY=
 github.com/apache/arrow/go/arrow v0.0.0-20211013220434-5962184e7a30/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs=
+github.com/appleboy/gin-jwt/v2 v2.10.3 h1:KNcPC+XPRNpuoBh+j+rgs5bQxN+SwG/0tHbIqpRoBGc=
+github.com/appleboy/gin-jwt/v2 v2.10.3/go.mod h1:LDUaQ8mF2W6LyXIbd5wqlV2SFebuyYs4RDwqMNgpsp8=
+github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS3rf4=
+github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
@@ -177,6 +181,11 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2
 github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
 github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
 github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
+github.com/bytedance/sonic v1.12.9 h1:Od1BvK55NnewtGaJsTDeAOSnLVO2BTSLOe0+ooKokmQ=
+github.com/bytedance/sonic v1.12.9/go.mod h1:uVvFidNmlt9+wa31S1urfwwthTWteBgG0hWuoKAXTx8=
+github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
+github.com/bytedance/sonic/loader v0.2.3 h1:yctD0Q3v2NOGfSWPLPvG2ggA2kV6TS6s4wioyEqssH0=
+github.com/bytedance/sonic/loader v0.2.3/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
 github.com/casdoor/casdoor-go-sdk v1.3.0 h1:iUZKsrNUkhtAoyitFIFw3e6TchctAdoxmVgLDtNAgpc=
 github.com/casdoor/casdoor-go-sdk v1.3.0/go.mod h1:cMnkCQJgMYpgAlgEx8reSt1AVaDIQLcJ1zk5pzBaz+4=
 github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
@@ -206,6 +215,9 @@ github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJ
 github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
+github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
+github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
+github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@@ -419,17 +431,20 @@ github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0
 github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
 github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8=
 github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8=
+github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
+github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
 github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
 github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
 github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/gin-contrib/cors v1.3.1 h1:doAsuITavI4IOcd0Y19U4B+O0dNWihRyX//nn4sEmgA=
 github.com/gin-contrib/cors v1.3.1/go.mod h1:jjEJ4268OPZUcU7k9Pm653S7lXUGcqMADzFA61xsmDk=
-github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
 github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
+github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
 github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
-github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM=
-github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
+github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
+github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
 github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
 github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks=
 github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY=
@@ -469,16 +484,16 @@ github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dp
 github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
 github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
 github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
-github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
-github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
+github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
 github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
-github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
-github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
 github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
-github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
-github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
-github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
-github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8=
+github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
 github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
 github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
 github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
@@ -510,6 +525,8 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe
 github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
 github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
 github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
+github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
+github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
 github.com/gocql/gocql v0.0.0-20210515062232-b7ef815b4556/go.mod h1:DL0ekTmBSTdlNF25Orwt/JMzqIq3EJ4MVa/J/uK64OY=
 github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
 github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
@@ -530,8 +547,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
-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-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
+github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang-migrate/migrate/v4 v4.15.2 h1:vU+M05vs6jWHKDdmE1Ecwj0BznygFc4QsdRe2E/L7kc=
 github.com/golang-migrate/migrate/v4 v4.15.2/go.mod h1:f2toGLkYqD3JH+Todi4aZ2ZdbeUNx4sIwiOK96rE9Lw=
 github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
@@ -594,6 +611,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
 github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE=
 github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
@@ -760,7 +778,6 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF
 github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -791,6 +808,10 @@ github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8
 github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
 github.com/klauspost/compress v1.15.13 h1:NFn1Wr8cfnenSJSA46lLq4wHCcBzKTSjnBIexDMMOV0=
 github.com/klauspost/compress v1.15.13/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
+github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
+github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -798,8 +819,9 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
 github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
@@ -808,8 +830,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq19sBYvuMoyQ4=
 github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
-github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
-github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
+github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
+github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
 github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@@ -846,8 +868,9 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
 github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
 github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
 github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
-github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
 github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
 github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
@@ -913,6 +936,7 @@ github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6Yf
 github.com/nats-io/jwt/v2 v2.3.0 h1:z2mA1a7tIf5ShggOFlR1oBPgd6hGqcDYsISxZByUzdI=
 github.com/nats-io/jwt/v2 v2.3.0/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k=
 github.com/nats-io/nats-server/v2 v2.9.10 h1:LMC46Oi9E6BUx/xBsaCVZgofliAqKQzRPU6eKWkN8jE=
+github.com/nats-io/nats-server/v2 v2.9.10/go.mod h1:AB6hAnGZDlYfqb7CTAm66ZKMZy9DpfierY1/PbpvI2g=
 github.com/nats-io/nats.go v1.22.1 h1:XzfqDspY0RNufzdrB8c4hFR+R3dahkxlpWe5+IWJzbE=
 github.com/nats-io/nats.go v1.22.1/go.mod h1:tLqubohF7t4z3du1QDPYJIQQyhb4wl6DhjxEajSI7UA=
 github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
@@ -940,6 +964,7 @@ github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1ls
 github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
 github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
 github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
+github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
 github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
 github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
 github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@@ -950,6 +975,7 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
 github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
 github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
 github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
+github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
 github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
 github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
 github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@@ -987,6 +1013,8 @@ github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrap
 github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
 github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
 github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
+github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
+github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
 github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
 github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
@@ -1045,6 +1073,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
 github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
+github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
 github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
 github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
 github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
@@ -1113,6 +1143,9 @@ github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
 github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -1120,23 +1153,36 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
 github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
 github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
+github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
+github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
+github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
 github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
+github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
 github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
-github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
 github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
+github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
+github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
 github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
@@ -1166,8 +1212,8 @@ github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
-github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk=
-github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4=
+github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
+github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -1242,6 +1288,8 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=
 go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
+golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4=
+golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
 golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -1269,8 +1317,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm
 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
+golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
 golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1389,8 +1437,8 @@ golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qx
 golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos=
-golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
+golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
 golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -1424,8 +1472,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
+golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
 golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1553,8 +1601,9 @@ golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
+golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -1571,8 +1620,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
+golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
 golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1583,6 +1632,7 @@ golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxb
 golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
+golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1664,7 +1714,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
+golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
+golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
 golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1839,8 +1890,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
-google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
+google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -1885,6 +1936,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gorm.io/driver/postgres v1.0.8/go.mod h1:4eOzrI1MUfm6ObJU/UcmbXyiHSs8jSwH95G5P5dxcAg=
 gorm.io/gorm v1.20.12/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
 gorm.io/gorm v1.21.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
@@ -1968,6 +2020,7 @@ modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
 modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
 modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
 modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4=
+nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=

+ 4 - 5
src/main.go

@@ -2,14 +2,12 @@ package main
 
 import (
 	"cmf/api"
-	"cmf/bus"
 	"cmf/conf"
 	"cmf/db"
 	"cmf/log"
 	"flag"
 
 	"go.uber.org/dig"
-	"infish.cn/comm"
 )
 
 var confFile = flag.String("conf", "./app.yaml", "conf file")
@@ -21,7 +19,7 @@ func BuildApp() *dig.Container {
 		return conf.NewAppConf(*confFile)
 	})
 
-	_ = app.Provide(bus.NewNatsBus)
+	// _ = app.Provide(bus.NewNatsBus)
 	_ = app.Provide(db.NewMongoDB)
 	// _ = app.Provide(db.NewRedisClient)
 	_ = app.Provide(api.NewHttpService)
@@ -30,12 +28,13 @@ func BuildApp() *dig.Container {
 }
 
 func main() {
+	StartMongo()
 
 	flag.Parse()
 	app := BuildApp()
 
-	err := app.Invoke(func(svc *api.Service, natsbus *comm.NatsBus) error {
-		go natsbus.Run(nil)
+	err := app.Invoke(func(svc *api.Service) error {
+		// go natsbus.Run(nil)
 
 		svc.Run()
 		return nil

+ 80 - 0
src/start_mongodb.go

@@ -0,0 +1,80 @@
+package main
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"log"
+	"os"
+	"os/exec"
+	"path/filepath"
+)
+
+func StartMongo() {
+	homeDir := "bin"
+	// 定义数据和日志目录
+	dataDir := filepath.Join(homeDir, "db")
+	logDir := filepath.Join(homeDir, "log")
+
+	// 确保目录存在
+	if err := ensureDir(dataDir); err != nil {
+		log.Fatalf("创建数据目录失败: %v", err)
+	}
+	if err := ensureDir(logDir); err != nil {
+		log.Fatalf("创建日志目录失败: %v", err)
+	}
+
+	// MongoDB 可执行文件路径
+	mongodPath := "./bin/mongodb-x86_64-4.4.29/bin/mongod"
+	logFile := filepath.Join(logDir, "mongod.log")
+
+	// 重新启动 MongoDB,这次启用认证
+	restartCmd := exec.Command(mongodPath,
+		"--dbpath", dataDir,
+		"--logpath", logFile,
+		"--auth")
+
+	// 使用StdoutPipe和StderrPipe来获取实时输出
+	stdout, err := restartCmd.StdoutPipe()
+	if err != nil {
+		log.Fatalf("获取标准输出失败: %v", err)
+	}
+	stderr, err := restartCmd.StderrPipe()
+	if err != nil {
+		log.Fatalf("获取标准错误失败: %v", err)
+	}
+
+	// 启动命令但不等待完成
+	if err := restartCmd.Start(); err != nil {
+		log.Fatalf("启动 MongoDB 失败: %v", err)
+	}
+
+	// 在后台协程中读取并打印输出
+	go func() {
+		// 合并标准输出和错误输出
+		combined := io.MultiReader(stdout, stderr)
+		scanner := bufio.NewScanner(combined)
+		for scanner.Scan() {
+			fmt.Println("MongoDB:", scanner.Text())
+		}
+		if err := scanner.Err(); err != nil {
+			fmt.Printf("读取MongoDB输出错误: %v\n", err)
+		}
+	}()
+
+	go func() {
+		if err := restartCmd.Wait(); err != nil {
+			fmt.Printf("MongoDB 进程退出,错误: %v\n", err)
+		} else {
+			fmt.Println("MongoDB 进程正常退出")
+		}
+	}()
+}
+
+// 确保目录存在
+func ensureDir(dir string) error {
+	if _, err := os.Stat(dir); os.IsNotExist(err) {
+		return os.MkdirAll(dir, 0755)
+	}
+	return nil
+}

File diff suppressed because it is too large
+ 0 - 0
src/static/css/240.05f7c25f.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/240.9cec3cf6.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/278.b4c3c5ef.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/301.335fe4b6.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/301.d5d05c9f.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/314.0514518c.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/314.9df3d594.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/331.18d162f5.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/331.1dc3bf48.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/335.b8c109e0.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/460.900a8fe0.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/460.ba801ed4.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/493.d92bcb46.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/493.d985bd14.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/533.1d4799b3.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/533.bc4d415e.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/64.335fe4b6.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/64.d5d05c9f.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/641.038fcf15.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/641.2c0a1f91.css


+ 1 - 0
src/static/css/986.03005caf.css

@@ -0,0 +1 @@
+.i1pkwmk6{position:relative;width:120px;height:120px;padding:6px;margin:0 auto;display:flex;align-items:center;justify-content:center;border:1px dashed #999;color:#999;border-radius:50%;cursor:pointer}.i1pkwmk6 img{width:100%;height:100%;border-radius:50%;-o-object-fit:contain;object-fit:contain}.i1pkwmk6 .edit_btn{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);opacity:0}.i1pkwmk6:hover .edit_btn{opacity:1}

+ 1 - 0
src/static/css/986.253c887d.css

@@ -0,0 +1 @@
+:root{--border-color:#eaeaea;--input-bg:#eee;--layout-bg:#eaeaea;--component-bg:#fff;--primary-color:#5a7bef;--primary-color-opacity:rgba(90,123,239,.1);--text-color:#464646;--text-active-color:#333;--text-passive-color:#999;--text-error-color:#ff4d4f;--input-hover-border-color:rgba(252,254,255,.3);--modal-background-color:#fff}.i1pkwmk6{position:relative;width:120px;height:120px;padding:6px;margin:0 auto;display:flex;align-items:center;justify-content:center;border:1px dashed #999;color:#999;border-radius:50%;cursor:pointer}.i1pkwmk6 img{width:100%;height:100%;border-radius:50%;-o-object-fit:contain;object-fit:contain}.i1pkwmk6 .edit_btn{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);opacity:0}.i1pkwmk6:hover .edit_btn{opacity:1}

File diff suppressed because it is too large
+ 0 - 0
src/static/css/chunk-vendors.56e805c9.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/chunk-vendors.c2ac48b0.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/index.77a408e1.css


File diff suppressed because it is too large
+ 0 - 0
src/static/css/index.bd9dc691.css


二進制
src/static/favicon.ico


二進制
src/static/img/banner.97a62f46.png


二進制
src/static/img/bg.89607e29.png


+ 1 - 0
src/static/index.html

@@ -0,0 +1 @@
+<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>cmfadmin</title><script defer="defer" src="js/chunk-vendors.73d0a11e.js"></script><script defer="defer" src="js/index.3402942e.js"></script><link href="css/chunk-vendors.56e805c9.css" rel="stylesheet"><link href="css/index.bd9dc691.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but cmfadmin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>

File diff suppressed because it is too large
+ 0 - 0
src/static/js/240.10a5987f.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/240.10a5987f.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/240.30f55128.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/240.30f55128.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/278.0c4c9e36.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/278.0c4c9e36.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/301.6732d5fb.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/301.6732d5fb.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/301.a5f6d222.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/301.a5f6d222.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/314.720c7ad1.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/314.720c7ad1.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/314.a21616f1.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/314.a21616f1.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/331.303036ef.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/331.303036ef.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/331.37c87581.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/331.37c87581.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/335.274bb63c.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/335.274bb63c.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/335.49ff737f.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/335.49ff737f.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/335.79b18870.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/335.79b18870.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/460.25c3593f.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/460.25c3593f.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/460.748246c0.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/460.748246c0.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/47.ef20937f.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/47.ef20937f.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/493.0351ca68.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/493.0351ca68.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/493.638f7506.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/493.638f7506.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/533.5b28713a.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/533.5b28713a.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/533.ff7f86df.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/533.ff7f86df.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/64.3506c92c.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/64.3506c92c.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/64.45bd4d08.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/64.45bd4d08.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/641.25ad542f.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/641.25ad542f.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/641.47532478.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/641.47532478.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/664.3719fbae.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/664.3719fbae.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/705.6cf720bc.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/705.6cf720bc.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/705.9267a874.js


File diff suppressed because it is too large
+ 0 - 0
src/static/js/705.9267a874.js.map


File diff suppressed because it is too large
+ 0 - 0
src/static/js/759.66f7f960.js


Some files were not shown because too many files changed in this diff