casbin.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. package service
  2. import (
  3. "context"
  4. "github.com/casbin/casbin/v2"
  5. "github.com/casbin/casbin/v2/model"
  6. "github.com/casbin/casbin/v2/persist"
  7. "github.com/gogf/gf/v2/frame/g"
  8. "github.com/tiger1103/gfast/v3/internal/app/common/model/entity"
  9. "github.com/tiger1103/gfast/v3/internal/app/common/service/internal/dao"
  10. "sync"
  11. )
  12. type cabinImpl struct{}
  13. type adapterCasbin struct {
  14. Enforcer *casbin.SyncedEnforcer
  15. EnforcerErr error
  16. ctx context.Context
  17. }
  18. var (
  19. cb = cabinImpl{}
  20. once sync.Once
  21. ac *adapterCasbin
  22. )
  23. // CasbinEnforcer 获取adapter单例对象
  24. func CasbinEnforcer(ctx context.Context) (enforcer *casbin.SyncedEnforcer, err error) {
  25. once.Do(func() {
  26. ac = cb.newAdapter(ctx)
  27. })
  28. enforcer = ac.Enforcer
  29. err = ac.EnforcerErr
  30. return
  31. }
  32. //初始化adapter操作
  33. func (s *cabinImpl) newAdapter(ctx context.Context) (a *adapterCasbin) {
  34. a = new(adapterCasbin)
  35. a.initPolicy(ctx)
  36. a.ctx = ctx
  37. return
  38. }
  39. func (a *adapterCasbin) initPolicy(ctx context.Context) {
  40. // Because the DB is empty at first,
  41. // so we need to load the policy from the file adapter (.CSV) first.
  42. e, err := casbin.NewSyncedEnforcer(g.Cfg().MustGet(ctx, "casbin.modelFile").String(), a)
  43. if err != nil {
  44. a.EnforcerErr = err
  45. return
  46. }
  47. // This is a trick to save the current policy to the DB.
  48. // We can't call e.SavePolicy() because the adapter in the enforcer is still the file adapter.
  49. // The current policy means the policy in the Casbin enforcer (aka in memory).
  50. //err = a.SavePolicy(e.GetModel())
  51. //if err != nil {
  52. // return err
  53. //}
  54. //set adapter
  55. //e.SetAdapter(a)
  56. // Clear the current policy.
  57. e.ClearPolicy()
  58. a.Enforcer = e
  59. // Load the policy from DB.
  60. err = a.LoadPolicy(e.GetModel())
  61. if err != nil {
  62. a.EnforcerErr = err
  63. return
  64. }
  65. }
  66. // SavePolicy saves policy to database.
  67. func (a *adapterCasbin) SavePolicy(model model.Model) (err error) {
  68. err = a.dropTable()
  69. if err != nil {
  70. return
  71. }
  72. err = a.createTable()
  73. if err != nil {
  74. return
  75. }
  76. for ptype, ast := range model["p"] {
  77. for _, rule := range ast.Policy {
  78. line := savePolicyLine(ptype, rule)
  79. _, err := dao.CasbinRule.Ctx(a.ctx).Data(line).Insert()
  80. if err != nil {
  81. return err
  82. }
  83. }
  84. }
  85. for ptype, ast := range model["g"] {
  86. for _, rule := range ast.Policy {
  87. line := savePolicyLine(ptype, rule)
  88. _, err := dao.CasbinRule.Ctx(a.ctx).Data(line).Insert()
  89. if err != nil {
  90. return err
  91. }
  92. }
  93. }
  94. return
  95. }
  96. func (a *adapterCasbin) dropTable() (err error) {
  97. return
  98. }
  99. func (a *adapterCasbin) createTable() (err error) {
  100. return
  101. }
  102. // LoadPolicy loads policy from database.
  103. func (a *adapterCasbin) LoadPolicy(model model.Model) error {
  104. var lines []*entity.CasbinRule
  105. if err := dao.CasbinRule.Ctx(a.ctx).Scan(&lines); err != nil {
  106. return err
  107. }
  108. for _, line := range lines {
  109. loadPolicyLine(line, model)
  110. }
  111. return nil
  112. }
  113. // AddPolicy adds a policy rule to the storage.
  114. func (a *adapterCasbin) AddPolicy(sec string, ptype string, rule []string) error {
  115. line := savePolicyLine(ptype, rule)
  116. _, err := dao.CasbinRule.Ctx(a.ctx).Data(line).Insert()
  117. return err
  118. }
  119. // RemovePolicy removes a policy rule from the storage.
  120. func (a *adapterCasbin) RemovePolicy(sec string, ptype string, rule []string) error {
  121. line := savePolicyLine(ptype, rule)
  122. err := rawDelete(a, line)
  123. return err
  124. }
  125. // RemoveFilteredPolicy removes policy rules that match the filter from the storage.
  126. func (a *adapterCasbin) RemoveFilteredPolicy(sec string, ptype string,
  127. fieldIndex int, fieldValues ...string) error {
  128. line := &entity.CasbinRule{}
  129. line.Ptype = ptype
  130. if fieldIndex <= 0 && 0 < fieldIndex+len(fieldValues) {
  131. line.V0 = fieldValues[0-fieldIndex]
  132. }
  133. if fieldIndex <= 1 && 1 < fieldIndex+len(fieldValues) {
  134. line.V1 = fieldValues[1-fieldIndex]
  135. }
  136. if fieldIndex <= 2 && 2 < fieldIndex+len(fieldValues) {
  137. line.V2 = fieldValues[2-fieldIndex]
  138. }
  139. if fieldIndex <= 3 && 3 < fieldIndex+len(fieldValues) {
  140. line.V3 = fieldValues[3-fieldIndex]
  141. }
  142. if fieldIndex <= 4 && 4 < fieldIndex+len(fieldValues) {
  143. line.V4 = fieldValues[4-fieldIndex]
  144. }
  145. if fieldIndex <= 5 && 5 < fieldIndex+len(fieldValues) {
  146. line.V5 = fieldValues[5-fieldIndex]
  147. }
  148. err := rawDelete(a, line)
  149. return err
  150. }
  151. func loadPolicyLine(line *entity.CasbinRule, model model.Model) {
  152. lineText := line.Ptype
  153. if line.V0 != "" {
  154. lineText += ", " + line.V0
  155. }
  156. if line.V1 != "" {
  157. lineText += ", " + line.V1
  158. }
  159. if line.V2 != "" {
  160. lineText += ", " + line.V2
  161. }
  162. if line.V3 != "" {
  163. lineText += ", " + line.V3
  164. }
  165. if line.V4 != "" {
  166. lineText += ", " + line.V4
  167. }
  168. if line.V5 != "" {
  169. lineText += ", " + line.V5
  170. }
  171. persist.LoadPolicyLine(lineText, model)
  172. }
  173. func savePolicyLine(ptype string, rule []string) *entity.CasbinRule {
  174. line := &entity.CasbinRule{}
  175. line.Ptype = ptype
  176. if len(rule) > 0 {
  177. line.V0 = rule[0]
  178. }
  179. if len(rule) > 1 {
  180. line.V1 = rule[1]
  181. }
  182. if len(rule) > 2 {
  183. line.V2 = rule[2]
  184. }
  185. if len(rule) > 3 {
  186. line.V3 = rule[3]
  187. }
  188. if len(rule) > 4 {
  189. line.V4 = rule[4]
  190. }
  191. if len(rule) > 5 {
  192. line.V5 = rule[5]
  193. }
  194. return line
  195. }
  196. func rawDelete(a *adapterCasbin, line *entity.CasbinRule) error {
  197. db := dao.CasbinRule.Ctx(a.ctx).Where("ptype = ?", line.Ptype)
  198. if line.V0 != "" {
  199. db = db.Where("v0 = ?", line.V0)
  200. }
  201. if line.V1 != "" {
  202. db = db.Where("v1 = ?", line.V1)
  203. }
  204. if line.V2 != "" {
  205. db = db.Where("v2 = ?", line.V2)
  206. }
  207. if line.V3 != "" {
  208. db = db.Where("v3 = ?", line.V3)
  209. }
  210. if line.V4 != "" {
  211. db = db.Where("v4 = ?", line.V4)
  212. }
  213. if line.V5 != "" {
  214. db = db.Where("v5 = ?", line.V5)
  215. }
  216. _, err := db.Delete()
  217. return err
  218. }