package service import ( "dy-admin/internal/pcmserver/global" "dy-admin/internal/pcmserver/pkg/code" "dy-admin/internal/pcmserver/sys/model/request" "dy-admin/pkg/log" "dy-admin/pkg/rescode" "github.com/casbin/casbin/v2" "github.com/casbin/casbin/v2/model" gormadapter "github.com/casbin/gorm-adapter/v3" "go.uber.org/zap" "strconv" "sync" ) type CasbinService struct{} var CasbinServiceInstance = new(CasbinService) // UpdateCasbin 更新角色对应的casbin权限规则 func (cs *CasbinService) UpdateCasbin(roleId int, casbinInfos []request.CasbinInfo) error { roleIdStr := strconv.Itoa(roleId) cs.ClearCasbin(0, roleIdStr) rules := make([][]string, 0, len(casbinInfos)) for _, v := range casbinInfos { rules = append(rules, []string{roleIdStr, v.Path, v.Action}) } e := cs.Casbin() success, err := e.AddPolicies(rules) if !success { return rescode.RegisterErrorWithCause(err, code.ErrCodeMap[code.ErrCasbinInternalCode]) } err = e.InvalidateCache() if err != nil { return rescode.RegisterErrorWithCause(err, code.ErrCodeMap[code.ErrCasbinInternalCode]) } return nil } // UpdateCasbinApi 更新casbinApi func (cs *CasbinService) UpdateCasbinApi(oldPath string, newPath string, oldMethod string, newMethod string) error { global.DB.Model(&gormadapter.CasbinRule{}).Where("v1 = ? AND v2 = ?", oldPath, oldMethod).Updates(map[string]interface{}{ "v1": newPath, "v2": newMethod, }) e := cs.Casbin() err := e.InvalidateCache() if err != nil { return rescode.RegisterErrorWithCause(err, code.ErrCodeMap[code.ErrCasbinInternalCode]) } return nil } // GetPolicyPathByAuthorityId 获取权限列表 func (cs *CasbinService) GetPolicyPathByAuthorityId(roleID uint) (pathMaps []request.CasbinInfo) { e := cs.Casbin() roleIDStr := strconv.Itoa(int(roleID)) list := e.GetFilteredPolicy(0, roleIDStr) for _, v := range list { pathMaps = append(pathMaps, request.CasbinInfo{ Path: v[1], Action: v[2], }) } return pathMaps } func (cs *CasbinService) ClearCasbin(v int, p ...string) (bool, error) { e := cs.Casbin() success, err := e.RemoveFilteredPolicy(v, p...) return success, err } var ( cachedEnforcer *casbin.CachedEnforcer once sync.Once ) func (cs *CasbinService) Casbin() *casbin.CachedEnforcer { once.Do(func() { a, _ := gormadapter.NewAdapterByDB(global.DB) 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 && keyMatch(r.obj,p.obj) && r.act == p.act ` m, err := model.NewModelFromString(text) if err != nil { log.Error("字符串加载模型失败!", zap.Error(err)) return } cachedEnforcer, _ = casbin.NewCachedEnforcer(m, a) cachedEnforcer.SetExpireTime(60 * 60) _ = cachedEnforcer.LoadPolicy() }) return cachedEnforcer }