发布dev2.8.2版本 (#2025)
* refactor(server): 重构服务器启动和重载逻辑 将服务器启动和重载逻辑进行重构,提取初始化系统为单独函数,优化代码结构。删除冗余的服务器初始化文件,统一使用新的 `server_run.go` 实现优雅关闭和重载功能。同时,将“重启服务”改为“重载服务”以更准确地描述功能。 * refactor: 重构系统事件处理、JWT和Casbin相关逻辑 - 将系统重载逻辑提取到独立的`system_events.go`文件中,并引入全局事件管理器 - 将JWT相关操作从`service`层移动到`utils`层,减少服务层依赖 - 将Casbin实例管理逻辑提取到`utils`层,统一管理Casbin实例的初始化和获取 - 删除冗余的`CreateSysOperationRecord`方法,优化操作记录中间件逻辑 * refactor(server): 重构服务初始化和关闭逻辑 将 `RunServer` 函数重命名为 `initServer`,并调整其调用方式以简化代码。同时,在系统初始化时添加 `SetupHandlers` 函数以注册全局处理函数,提升代码可维护性。 * fix: 修复自动化代码enum查询条件的bug * fix: 修复组合模式下,顶部菜单重复bug * refactor: 修改名称 RunWindowsServer ==> RunServer * 新增mcp * feat: 支持mcp服务 * feat:调整mcp结构,增加客户端和测试用例 * feat:更换mcp基础包和结构 * feat:提交客户端工具测试用例 * feat: 增加自动创建 mcp Tool模板 功能 * fix: 增加默认值属性 * feat: 调整初始化menu的逻辑 * feat: 调整初始config.yaml * feat: 增加全局GVA_MCP_SERVER属性,方便灵活化开发。 * feat: 优化自动化mcp逻辑和成功展示 * feat: 优化mcp tool nickname工具 * feat: 发布2.8.2 Beta版本 --------- Co-authored-by: piexlMax(奇淼 <qimiaojiangjizhao@gmail.com> Co-authored-by: Gor-c <creup@outlook.com> Co-authored-by: QIN xiansheng <sjjlnaps@163.com>
This commit is contained in:
45
server/service/system/auto_code_mcp.go
Normal file
45
server/service/system/auto_code_mcp.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils/autocode"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
func (s *autoCodeTemplate) CreateMcp(ctx context.Context, info request.AutoMcpTool) (toolFilePath string, err error) {
|
||||
mcpTemplatePath := filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "resource", "mcp", "tools.tpl")
|
||||
mcpToolPath := filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "mcp")
|
||||
|
||||
var files *template.Template
|
||||
|
||||
templateName := filepath.Base(mcpTemplatePath)
|
||||
|
||||
files, err = template.New(templateName).Funcs(autocode.GetTemplateFuncMap()).ParseFiles(mcpTemplatePath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fileName := utils.HumpToUnderscore(info.Name)
|
||||
|
||||
toolFilePath = filepath.Join(mcpToolPath, fileName+".go")
|
||||
|
||||
f, err := os.Create(toolFilePath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// 执行模板,将内容写入文件
|
||||
err = files.Execute(f, info)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
}
|
@@ -233,6 +233,9 @@ func (s *autoCodePackage) Templates(ctx context.Context) ([]string, error) {
|
||||
if entries[i].Name() == "preview" {
|
||||
continue
|
||||
} // preview 为预览代码生成器的代码
|
||||
if entries[i].Name() == "mcp" {
|
||||
continue
|
||||
} // preview 为mcp生成器的代码
|
||||
templates = append(templates, entries[i].Name())
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
)
|
||||
|
||||
type JwtService struct{}
|
||||
@@ -29,20 +28,6 @@ func (jwtService *JwtService) JsonInBlacklist(jwtList system.JwtBlacklist) (err
|
||||
return
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: IsBlacklist
|
||||
//@description: 判断JWT是否在黑名单内部
|
||||
//@param: jwt string
|
||||
//@return: bool
|
||||
|
||||
func (jwtService *JwtService) IsBlacklist(jwt string) bool {
|
||||
_, ok := global.BlackCache.Get(jwt)
|
||||
return ok
|
||||
// err := global.GVA_DB.Where("jwt = ?", jwt).First(&system.JwtBlacklist{}).Error
|
||||
// isNotFound := errors.Is(err, gorm.ErrRecordNotFound)
|
||||
// return !isNotFound
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetRedisJWT
|
||||
//@description: 从redis取jwt
|
||||
@@ -54,23 +39,6 @@ func (jwtService *JwtService) GetRedisJWT(userName string) (redisJWT string, err
|
||||
return redisJWT, err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: SetRedisJWT
|
||||
//@description: jwt存入redis并设置过期时间
|
||||
//@param: jwt string, userName string
|
||||
//@return: err error
|
||||
|
||||
func (jwtService *JwtService) SetRedisJWT(jwt string, userName string) (err error) {
|
||||
// 此处过期时间等于jwt过期时间
|
||||
dr, err := utils.ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
timer := dr
|
||||
err = global.GVA_REDIS.Set(context.Background(), userName, jwt, timer).Err()
|
||||
return err
|
||||
}
|
||||
|
||||
func LoadAll() {
|
||||
var data []string
|
||||
err := global.GVA_DB.Model(&system.JwtBlacklist{}).Select("jwt").Find(&data).Error
|
||||
|
@@ -3,17 +3,14 @@ package system
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/casbin/casbin/v2"
|
||||
"github.com/casbin/casbin/v2/model"
|
||||
gormadapter "github.com/casbin/gorm-adapter/v3"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
@@ -68,7 +65,7 @@ func (casbinService *CasbinService) UpdateCasbin(adminAuthorityID, AuthorityID u
|
||||
if len(rules) == 0 {
|
||||
return nil
|
||||
} // 设置空权限无需调用 AddPolicies 方法
|
||||
e := casbinService.Casbin()
|
||||
e := utils.GetCasbin()
|
||||
success, _ := e.AddPolicies(rules)
|
||||
if !success {
|
||||
return errors.New("存在相同api,添加失败,请联系管理员")
|
||||
@@ -91,7 +88,7 @@ func (casbinService *CasbinService) UpdateCasbinApi(oldPath string, newPath stri
|
||||
return err
|
||||
}
|
||||
|
||||
e := casbinService.Casbin()
|
||||
e := utils.GetCasbin()
|
||||
return e.LoadPolicy()
|
||||
}
|
||||
|
||||
@@ -102,7 +99,7 @@ func (casbinService *CasbinService) UpdateCasbinApi(oldPath string, newPath stri
|
||||
//@return: pathMaps []request.CasbinInfo
|
||||
|
||||
func (casbinService *CasbinService) GetPolicyPathByAuthorityId(AuthorityID uint) (pathMaps []request.CasbinInfo) {
|
||||
e := casbinService.Casbin()
|
||||
e := utils.GetCasbin()
|
||||
authorityId := strconv.Itoa(int(AuthorityID))
|
||||
list, _ := e.GetFilteredPolicy(0, authorityId)
|
||||
for _, v := range list {
|
||||
@@ -121,7 +118,7 @@ func (casbinService *CasbinService) GetPolicyPathByAuthorityId(AuthorityID uint)
|
||||
//@return: bool
|
||||
|
||||
func (casbinService *CasbinService) ClearCasbin(v int, p ...string) bool {
|
||||
e := casbinService.Casbin()
|
||||
e := utils.GetCasbin()
|
||||
success, _ := e.RemoveFilteredPolicy(v, p...)
|
||||
return success
|
||||
}
|
||||
@@ -170,52 +167,7 @@ func (casbinService *CasbinService) AddPolicies(db *gorm.DB, rules [][]string) e
|
||||
}
|
||||
|
||||
func (casbinService *CasbinService) FreshCasbin() (err error) {
|
||||
e := casbinService.Casbin()
|
||||
e := utils.GetCasbin()
|
||||
err = e.LoadPolicy()
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: Casbin
|
||||
//@description: 持久化到数据库 引入自定义规则
|
||||
//@return: *casbin.Enforcer
|
||||
|
||||
var (
|
||||
syncedCachedEnforcer *casbin.SyncedCachedEnforcer
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
func (casbinService *CasbinService) Casbin() *casbin.SyncedCachedEnforcer {
|
||||
once.Do(func() {
|
||||
a, err := gormadapter.NewAdapterByDB(global.GVA_DB)
|
||||
if err != nil {
|
||||
zap.L().Error("适配数据库失败请检查casbin表是否为InnoDB引擎!", zap.Error(err))
|
||||
return
|
||||
}
|
||||
text := `
|
||||
[request_definition]
|
||||
r = sub, obj, act
|
||||
|
||||
[policy_definition]
|
||||
p = sub, obj, act
|
||||
|
||||
[role_definition]
|
||||
g = _, _
|
||||
|
||||
[policy_effect]
|
||||
e = some(where (p.eft == allow))
|
||||
|
||||
[matchers]
|
||||
m = r.sub == p.sub && keyMatch2(r.obj,p.obj) && r.act == p.act
|
||||
`
|
||||
m, err := model.NewModelFromString(text)
|
||||
if err != nil {
|
||||
zap.L().Error("字符串加载模型失败!", zap.Error(err))
|
||||
return
|
||||
}
|
||||
syncedCachedEnforcer, _ = casbin.NewSyncedCachedEnforcer(m, a)
|
||||
syncedCachedEnforcer.SetExpireTime(60 * 60)
|
||||
_ = syncedCachedEnforcer.LoadPolicy()
|
||||
})
|
||||
return syncedCachedEnforcer
|
||||
}
|
||||
|
@@ -17,11 +17,6 @@ type OperationRecordService struct{}
|
||||
|
||||
var OperationRecordServiceApp = new(OperationRecordService)
|
||||
|
||||
func (operationRecordService *OperationRecordService) CreateSysOperationRecord(sysOperationRecord system.SysOperationRecord) (err error) {
|
||||
err = global.GVA_DB.Create(&sysOperationRecord).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [granty1](https://github.com/granty1)
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: DeleteSysOperationRecordByIds
|
||||
|
Reference in New Issue
Block a user