From 35fa2d7a356bcd3263026916ffeaf6a68972cac6 Mon Sep 17 00:00:00 2001 From: pixelmaxQM Date: Sun, 25 Aug 2024 16:21:04 +0800 Subject: [PATCH] =?UTF-8?q?fixed:=20=E4=BF=AE=E5=A4=8D=E8=B7=A8=E7=BA=A7?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E8=A7=92=E8=89=B2=E6=9D=83=E9=99=90=E7=9A=84?= =?UTF-8?q?=E8=B6=8A=E6=9D=83=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/api/v1/system/sys_user.go | 7 +- server/service/system/sys_authority.go | 36 ++++- server/service/system/sys_casbin.go | 18 +++ server/service/system/sys_user.go | 22 ++- server/utils/injection_code.go | 180 ------------------------- 5 files changed, 78 insertions(+), 185 deletions(-) delete mode 100644 server/utils/injection_code.go diff --git a/server/api/v1/system/sys_user.go b/server/api/v1/system/sys_user.go index ceed664907..2dc83d3676 100644 --- a/server/api/v1/system/sys_user.go +++ b/server/api/v1/system/sys_user.go @@ -285,7 +285,8 @@ func (b *BaseApi) SetUserAuthorities(c *gin.Context) { response.FailWithMessage(err.Error(), c) return } - err = userService.SetUserAuthorities(sua.ID, sua.AuthorityIds) + authorityID := utils.GetUserAuthorityId(c) + err = userService.SetUserAuthorities(authorityID, sua.ID, sua.AuthorityIds) if err != nil { global.GVA_LOG.Error("修改失败!", zap.Error(err)) response.FailWithMessage("修改失败", c) @@ -350,9 +351,9 @@ func (b *BaseApi) SetUserInfo(c *gin.Context) { response.FailWithMessage(err.Error(), c) return } - if len(user.AuthorityIds) != 0 { - err = userService.SetUserAuthorities(user.ID, user.AuthorityIds) + authorityID := utils.GetUserAuthorityId(c) + err = userService.SetUserAuthorities(authorityID, user.ID, user.AuthorityIds) if err != nil { global.GVA_LOG.Error("设置失败!", zap.Error(err)) response.FailWithMessage("设置失败", c) diff --git a/server/service/system/sys_authority.go b/server/service/system/sys_authority.go index 181e6e20f8..d99fb2af1b 100644 --- a/server/service/system/sys_authority.go +++ b/server/service/system/sys_authority.go @@ -183,7 +183,7 @@ func (authorityService *AuthorityService) DeleteAuthority(auth *system.SysAuthor //@param: info request.PageInfo //@return: list interface{}, total int64, err error -func (authorityService *AuthorityService) GetAuthorityInfoList(authorityID uint) (list any, err error) { +func (authorityService *AuthorityService) GetAuthorityInfoList(authorityID uint) (list []system.SysAuthority, err error) { var authority system.SysAuthority err = global.GVA_DB.Where("authority_id = ?", authorityID).First(&authority).Error if err != nil { @@ -210,6 +210,24 @@ func (authorityService *AuthorityService) GetAuthorityInfoList(authorityID uint) return authorities, err } +//@author: [piexlmax](https://github.com/piexlmax) +//@function: GetAuthorityInfoList +//@description: 分页获取数据 +//@param: info request.PageInfo +//@return: list interface{}, total int64, err error + +func (authorityService *AuthorityService) GetStructAuthorityList(authorityID uint) (list []uint, err error) { + var authorities []system.SysAuthority + err = global.GVA_DB.Preload("DataAuthorityId").Where("parent_id = ?", authorityID).Find(&authorities).Error + if len(authorities) > 0 { + for k := range authorities { + list = append(list, authorities[k].AuthorityId) + _, err = authorityService.GetStructAuthorityList(authorities[k].AuthorityId) + } + } + return list, err +} + //@author: [piexlmax](https://github.com/piexlmax) //@function: GetAuthorityInfo //@description: 获取所有角色信息 @@ -242,6 +260,22 @@ func (authorityService *AuthorityService) SetDataAuthority(auth system.SysAuthor func (authorityService *AuthorityService) SetMenuAuthority(auth *system.SysAuthority) error { var s system.SysAuthority + if global.GVA_CONFIG.System.UseStrictAuth { + authids, err := authorityService.GetStructAuthorityList(auth.AuthorityId) + if err != nil { + return err + } + hasAuth := false + for _, v := range authids { + if v == auth.AuthorityId { + hasAuth = true + break + } + } + if !hasAuth { + return errors.New("您提交的角色ID不合法") + } + } global.GVA_DB.Preload("SysBaseMenus").First(&s, "authority_id = ?", auth.AuthorityId) err := global.GVA_DB.Model(&s).Association("SysBaseMenus").Replace(&auth.SysBaseMenus) return err diff --git a/server/service/system/sys_casbin.go b/server/service/system/sys_casbin.go index 80b0091e9e..1f03a31b8f 100644 --- a/server/service/system/sys_casbin.go +++ b/server/service/system/sys_casbin.go @@ -27,6 +27,24 @@ type CasbinService struct{} var CasbinServiceApp = new(CasbinService) func (casbinService *CasbinService) UpdateCasbin(AuthorityID uint, casbinInfos []request.CasbinInfo) error { + + if global.GVA_CONFIG.System.UseStrictAuth { + authids, err := AuthorityServiceApp.GetStructAuthorityList(AuthorityID) + if err != nil { + return err + } + hasAuth := false + for _, v := range authids { + if v == AuthorityID { + hasAuth = true + break + } + } + if !hasAuth { + return errors.New("您提交的角色ID不合法") + } + } + authorityId := strconv.Itoa(int(AuthorityID)) casbinService.ClearCasbin(0, authorityId) rules := [][]string{} diff --git a/server/service/system/sys_user.go b/server/service/system/sys_user.go index 2c75f1f6f2..c0ec973fbd 100644 --- a/server/service/system/sys_user.go +++ b/server/service/system/sys_user.go @@ -152,7 +152,7 @@ func (userService *UserService) SetUserAuthority(id uint, authorityId uint) (err //@param: id uint, authorityIds []string //@return: err error -func (userService *UserService) SetUserAuthorities(id uint, authorityIds []uint) (err error) { +func (userService *UserService) SetUserAuthorities(adminAuthorityID, id uint, authorityIds []uint) (err error) { return global.GVA_DB.Transaction(func(tx *gorm.DB) error { var user system.SysUser TxErr := tx.Where("id = ?", id).First(&user).Error @@ -164,8 +164,28 @@ func (userService *UserService) SetUserAuthorities(id uint, authorityIds []uint) if TxErr != nil { return TxErr } + var childrenIDS []uint + if global.GVA_CONFIG.System.UseStrictAuth { + childrenIDS, err = AuthorityServiceApp.GetStructAuthorityList(adminAuthorityID) + if err != nil { + return errors.New("获取当前角色可用角色失败") + } + } + var useAuthority []system.SysUserAuthority for _, v := range authorityIds { + if global.GVA_CONFIG.System.UseStrictAuth { + hasAuth := false + for i := range childrenIDS { + if childrenIDS[i] == v { + hasAuth = true + break + } + } + if !hasAuth { + return errors.New("您提交的角色ID不合法") + } + } useAuthority = append(useAuthority, system.SysUserAuthority{ SysUserId: id, SysAuthorityAuthorityId: v, }) diff --git a/server/utils/injection_code.go b/server/utils/injection_code.go deleted file mode 100644 index 8427256c1a..0000000000 --- a/server/utils/injection_code.go +++ /dev/null @@ -1,180 +0,0 @@ -package utils - -import ( - "errors" - "fmt" - "go/ast" - "go/parser" - "go/token" - "os" - "strings" -) - -//@author: [LeonardWang](https://github.com/WangLeonard) -//@function: AutoInjectionCode -//@description: 向文件中固定注释位置写入代码 -//@param: filepath string, funcName string, codeData string -//@return: error - -const ( - startComment = "Code generated by github.com/flipped-aurora/gin-vue-admin/server Begin; DO NOT EDIT." - endComment = "Code generated by github.com/flipped-aurora/gin-vue-admin/server End; DO NOT EDIT." -) - -//@author: [LeonardWang](https://github.com/WangLeonard) -//@function: AutoInjectionCode -//@description: 向文件中固定注释位置写入代码 -//@param: filepath string, funcName string, codeData string -//@return: error - -func AutoInjectionCode(filepath string, funcName string, codeData string) error { - srcData, err := os.ReadFile(filepath) - if err != nil { - return err - } - srcDataLen := len(srcData) - fset := token.NewFileSet() - fparser, err := parser.ParseFile(fset, filepath, srcData, parser.ParseComments) - if err != nil { - return err - } - codeData = strings.TrimSpace(codeData) - codeStartPos := -1 - codeEndPos := srcDataLen - var expectedFunction *ast.FuncDecl - - startCommentPos := -1 - endCommentPos := srcDataLen - - // 如果指定了函数名,先寻找对应函数 - if funcName != "" { - for _, decl := range fparser.Decls { - if funDecl, ok := decl.(*ast.FuncDecl); ok && funDecl.Name.Name == funcName { - expectedFunction = funDecl - codeStartPos = int(funDecl.Body.Lbrace) - codeEndPos = int(funDecl.Body.Rbrace) - break - } - } - } - - // 遍历所有注释 - for _, comment := range fparser.Comments { - if int(comment.Pos()) > codeStartPos && int(comment.End()) <= codeEndPos { - if startComment != "" && strings.Contains(comment.Text(), startComment) { - startCommentPos = int(comment.Pos()) // Note: Pos is the second '/' - } - if endComment != "" && strings.Contains(comment.Text(), endComment) { - endCommentPos = int(comment.Pos()) // Note: Pos is the second '/' - } - } - } - - if endCommentPos == srcDataLen { - return fmt.Errorf("comment:%s not found", endComment) - } - - // 在指定函数名,且函数中startComment和endComment都存在时,进行区间查重 - if (codeStartPos != -1 && codeEndPos <= srcDataLen) && (startCommentPos != -1 && endCommentPos != srcDataLen) && expectedFunction != nil { - if exist := checkExist(&srcData, startCommentPos, endCommentPos, expectedFunction.Body, codeData); exist { - fmt.Printf("文件 %s 待插入数据 %s 已存在\n", filepath, codeData) - return nil // 这里不需要返回错误? - } - } - - // 两行注释中间没有换行时,会被认为是一条Comment - if startCommentPos == endCommentPos { - endCommentPos = startCommentPos + strings.Index(string(srcData[startCommentPos:]), endComment) - for srcData[endCommentPos] != '/' { - endCommentPos-- - } - } - - // 记录"//"之前的空字符,保持写入后的格式一致 - tmpSpace := make([]byte, 0, 10) - for tmp := endCommentPos - 2; tmp >= 0; tmp-- { - if srcData[tmp] != '\n' { - tmpSpace = append(tmpSpace, srcData[tmp]) - } else { - break - } - } - - reverseSpace := make([]byte, 0, len(tmpSpace)) - for index := len(tmpSpace) - 1; index >= 0; index-- { - reverseSpace = append(reverseSpace, tmpSpace[index]) - } - - // 插入数据 - indexPos := endCommentPos - 1 - insertData := []byte(append([]byte(codeData+"\n"), reverseSpace...)) - - remainData := append([]byte{}, srcData[indexPos:]...) - srcData = append(append(srcData[:indexPos], insertData...), remainData...) - - // 写回数据 - return os.WriteFile(filepath, srcData, 0o600) -} - -func checkExist(srcData *[]byte, startPos int, endPos int, blockStmt *ast.BlockStmt, target string) bool { - for _, list := range blockStmt.List { - switch stmt := list.(type) { - case *ast.ExprStmt: - if callExpr, ok := stmt.X.(*ast.CallExpr); ok && - int(callExpr.Pos()) > startPos && int(callExpr.End()) < endPos { - text := string((*srcData)[int(callExpr.Pos()-1):int(callExpr.End())]) - key := strings.TrimSpace(text) - if key == target { - return true - } - } - case *ast.BlockStmt: - if checkExist(srcData, startPos, endPos, stmt, target) { - return true - } - case *ast.AssignStmt: - // 为 model 中的代码进行检查 - if len(stmt.Rhs) > 0 { - if callExpr, ok := stmt.Rhs[0].(*ast.CallExpr); ok { - for _, arg := range callExpr.Args { - if int(arg.Pos()) > startPos && int(arg.End()) < endPos { - text := string((*srcData)[int(arg.Pos()-1):int(arg.End())]) - key := strings.TrimSpace(text) - if key == target { - return true - } - } - } - } - } - } - } - return false -} - -func AutoClearCode(filepath string, codeData string) error { - srcData, err := os.ReadFile(filepath) - if err != nil { - return err - } - srcData, err = cleanCode(codeData, string(srcData)) - if err != nil { - return err - } - return os.WriteFile(filepath, srcData, 0o600) -} - -func cleanCode(clearCode string, srcData string) ([]byte, error) { - bf := make([]rune, 0, 1024) - for i, v := range srcData { - if v == '\n' { - if strings.TrimSpace(string(bf)) == clearCode { - return append([]byte(srcData[:i-len(bf)]), []byte(srcData[i+1:])...), nil - } - bf = (bf)[:0] - continue - } - bf = append(bf, v) - } - return []byte(srcData), errors.New("未找到内容") -}