sys_casbin.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. package system
  2. import (
  3. "errors"
  4. "gorm.io/gorm"
  5. "strconv"
  6. "sync"
  7. "github.com/casbin/casbin/v2"
  8. "github.com/casbin/casbin/v2/model"
  9. gormadapter "github.com/casbin/gorm-adapter/v3"
  10. _ "github.com/go-sql-driver/mysql"
  11. "go.uber.org/zap"
  12. "server/global"
  13. "server/model/system/request"
  14. )
  15. //@author: [piexlmax](https://github.com/piexlmax)
  16. //@function: UpdateCasbin
  17. //@description: 更新casbin权限
  18. //@param: authorityId string, casbinInfos []request.CasbinInfo
  19. //@return: error
  20. type CasbinService struct{}
  21. var CasbinServiceApp = new(CasbinService)
  22. func (casbinService *CasbinService) UpdateCasbin(AuthorityID uint, casbinInfos []request.CasbinInfo) error {
  23. authorityId := strconv.Itoa(int(AuthorityID))
  24. casbinService.ClearCasbin(0, authorityId)
  25. rules := [][]string{}
  26. //做权限去重处理
  27. deduplicateMap := make(map[string]bool)
  28. for _, v := range casbinInfos {
  29. key := authorityId + v.Path + v.Method
  30. if _, ok := deduplicateMap[key]; !ok {
  31. deduplicateMap[key] = true
  32. rules = append(rules, []string{authorityId, v.Path, v.Method})
  33. }
  34. }
  35. e := casbinService.Casbin()
  36. success, _ := e.AddPolicies(rules)
  37. if !success {
  38. return errors.New("存在相同api,添加失败,请联系管理员")
  39. }
  40. return nil
  41. }
  42. //@author: [piexlmax](https://github.com/piexlmax)
  43. //@function: UpdateCasbinApi
  44. //@description: API更新随动
  45. //@param: oldPath string, newPath string, oldMethod string, newMethod string
  46. //@return: error
  47. func (casbinService *CasbinService) UpdateCasbinApi(oldPath string, newPath string, oldMethod string, newMethod string) error {
  48. err := global.GVA_DB.Model(&gormadapter.CasbinRule{}).Where("v1 = ? AND v2 = ?", oldPath, oldMethod).Updates(map[string]interface{}{
  49. "v1": newPath,
  50. "v2": newMethod,
  51. }).Error
  52. e := casbinService.Casbin()
  53. err = e.LoadPolicy()
  54. if err != nil {
  55. return err
  56. }
  57. return err
  58. }
  59. //@author: [piexlmax](https://github.com/piexlmax)
  60. //@function: GetPolicyPathByAuthorityId
  61. //@description: 获取权限列表
  62. //@param: authorityId string
  63. //@return: pathMaps []request.CasbinInfo
  64. func (casbinService *CasbinService) GetPolicyPathByAuthorityId(AuthorityID uint) (pathMaps []request.CasbinInfo) {
  65. e := casbinService.Casbin()
  66. authorityId := strconv.Itoa(int(AuthorityID))
  67. list := e.GetFilteredPolicy(0, authorityId)
  68. for _, v := range list {
  69. pathMaps = append(pathMaps, request.CasbinInfo{
  70. Path: v[1],
  71. Method: v[2],
  72. })
  73. }
  74. return pathMaps
  75. }
  76. //@author: [piexlmax](https://github.com/piexlmax)
  77. //@function: ClearCasbin
  78. //@description: 清除匹配的权限
  79. //@param: v int, p ...string
  80. //@return: bool
  81. func (casbinService *CasbinService) ClearCasbin(v int, p ...string) bool {
  82. e := casbinService.Casbin()
  83. success, _ := e.RemoveFilteredPolicy(v, p...)
  84. return success
  85. }
  86. //@author: [piexlmax](https://github.com/piexlmax)
  87. //@function: RemoveFilteredPolicy
  88. //@description: 使用数据库方法清理筛选的politicy 此方法需要调用FreshCasbin方法才可以在系统中即刻生效
  89. //@param: db *gorm.DB, authorityId string
  90. //@return: error
  91. func (casbinService *CasbinService) RemoveFilteredPolicy(db *gorm.DB, authorityId string) error {
  92. return db.Delete(&gormadapter.CasbinRule{}, "v0 = ?", authorityId).Error
  93. }
  94. //@author: [piexlmax](https://github.com/piexlmax)
  95. //@function: RemoveFilteredPolicy
  96. //@description: 同步目前数据库的policy 此方法需要调用FreshCasbin方法才可以在系统中即刻生效
  97. //@param: db *gorm.DB, authorityId string, rules [][]string
  98. //@return: error
  99. func (casbinService *CasbinService) SyncPolicy(db *gorm.DB, authorityId string, rules [][]string) error {
  100. err := casbinService.RemoveFilteredPolicy(db, authorityId)
  101. if err != nil {
  102. return err
  103. }
  104. return casbinService.AddPolicies(db, rules)
  105. }
  106. //@author: [piexlmax](https://github.com/piexlmax)
  107. //@function: ClearCasbin
  108. //@description: 清除匹配的权限
  109. //@param: v int, p ...string
  110. //@return: bool
  111. func (casbinService *CasbinService) AddPolicies(db *gorm.DB, rules [][]string) error {
  112. var casbinRules []gormadapter.CasbinRule
  113. for i := range rules {
  114. casbinRules = append(casbinRules, gormadapter.CasbinRule{
  115. Ptype: "p",
  116. V0: rules[i][0],
  117. V1: rules[i][1],
  118. V2: rules[i][2],
  119. })
  120. }
  121. return db.Create(&casbinRules).Error
  122. }
  123. func (CasbinService *CasbinService) FreshCasbin() (err error) {
  124. e := CasbinService.Casbin()
  125. err = e.LoadPolicy()
  126. return err
  127. }
  128. //@author: [piexlmax](https://github.com/piexlmax)
  129. //@function: Casbin
  130. //@description: 持久化到数据库 引入自定义规则
  131. //@return: *casbin.Enforcer
  132. var (
  133. syncedCachedEnforcer *casbin.SyncedCachedEnforcer
  134. once sync.Once
  135. )
  136. func (casbinService *CasbinService) Casbin() *casbin.SyncedCachedEnforcer {
  137. once.Do(func() {
  138. a, err := gormadapter.NewAdapterByDB(global.GVA_DB)
  139. if err != nil {
  140. zap.L().Error("适配数据库失败请检查casbin表是否为InnoDB引擎!", zap.Error(err))
  141. return
  142. }
  143. text := `
  144. [request_definition]
  145. r = sub, obj, act
  146. [policy_definition]
  147. p = sub, obj, act
  148. [role_definition]
  149. g = _, _
  150. [policy_effect]
  151. e = some(where (p.eft == allow))
  152. [matchers]
  153. m = r.sub == p.sub && keyMatch2(r.obj,p.obj) && r.act == p.act
  154. `
  155. m, err := model.NewModelFromString(text)
  156. if err != nil {
  157. zap.L().Error("字符串加载模型失败!", zap.Error(err))
  158. return
  159. }
  160. syncedCachedEnforcer, _ = casbin.NewSyncedCachedEnforcer(m, a)
  161. syncedCachedEnforcer.SetExpireTime(60 * 60)
  162. _ = syncedCachedEnforcer.LoadPolicy()
  163. })
  164. return syncedCachedEnforcer
  165. }