casbin.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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(),
  43. g.Cfg().MustGet(ctx, "casbin.policyFile").String())
  44. if err != nil {
  45. a.EnforcerErr = err
  46. return
  47. }
  48. // This is a trick to save the current policy to the DB.
  49. // We can't call e.SavePolicy() because the adapter in the enforcer is still the file adapter.
  50. // The current policy means the policy in the Casbin enforcer (aka in memory).
  51. //err = a.SavePolicy(e.GetModel())
  52. //if err != nil {
  53. // return err
  54. //}
  55. //set adapter
  56. e.SetAdapter(a)
  57. // Clear the current policy.
  58. e.ClearPolicy()
  59. a.Enforcer = e
  60. // Load the policy from DB.
  61. err = a.LoadPolicy(e.GetModel())
  62. if err != nil {
  63. a.EnforcerErr = err
  64. return
  65. }
  66. }
  67. // SavePolicy saves policy to database.
  68. func (a *adapterCasbin) SavePolicy(model model.Model) (err error) {
  69. err = a.dropTable()
  70. if err != nil {
  71. return
  72. }
  73. err = a.createTable()
  74. if err != nil {
  75. return
  76. }
  77. for ptype, ast := range model["p"] {
  78. for _, rule := range ast.Policy {
  79. line := savePolicyLine(ptype, rule)
  80. _, err := dao.CasbinRule.Ctx(a.ctx).Data(line).Insert()
  81. if err != nil {
  82. return err
  83. }
  84. }
  85. }
  86. for ptype, ast := range model["g"] {
  87. for _, rule := range ast.Policy {
  88. line := savePolicyLine(ptype, rule)
  89. _, err := dao.CasbinRule.Ctx(a.ctx).Data(line).Insert()
  90. if err != nil {
  91. return err
  92. }
  93. }
  94. }
  95. return
  96. }
  97. func (a *adapterCasbin) dropTable() (err error) {
  98. return
  99. }
  100. func (a *adapterCasbin) createTable() (err error) {
  101. return
  102. }
  103. // LoadPolicy loads policy from database.
  104. func (a *adapterCasbin) LoadPolicy(model model.Model) error {
  105. var lines []*entity.CasbinRule
  106. if err := dao.CasbinRule.Ctx(a.ctx).Scan(&lines); err != nil {
  107. return err
  108. }
  109. for _, line := range lines {
  110. loadPolicyLine(line, model)
  111. }
  112. return nil
  113. }
  114. // AddPolicy adds a policy rule to the storage.
  115. func (a *adapterCasbin) AddPolicy(sec string, ptype string, rule []string) error {
  116. line := savePolicyLine(ptype, rule)
  117. _, err := dao.CasbinRule.Ctx(a.ctx).Data(line).Insert()
  118. return err
  119. }
  120. // RemovePolicy removes a policy rule from the storage.
  121. func (a *adapterCasbin) RemovePolicy(sec string, ptype string, rule []string) error {
  122. line := savePolicyLine(ptype, rule)
  123. err := rawDelete(a, line)
  124. return err
  125. }
  126. // RemoveFilteredPolicy removes policy rules that match the filter from the storage.
  127. func (a *adapterCasbin) RemoveFilteredPolicy(sec string, ptype string,
  128. fieldIndex int, fieldValues ...string) error {
  129. line := &entity.CasbinRule{}
  130. line.Ptype = ptype
  131. if fieldIndex <= 0 && 0 < fieldIndex+len(fieldValues) {
  132. line.V0 = fieldValues[0-fieldIndex]
  133. }
  134. if fieldIndex <= 1 && 1 < fieldIndex+len(fieldValues) {
  135. line.V1 = fieldValues[1-fieldIndex]
  136. }
  137. if fieldIndex <= 2 && 2 < fieldIndex+len(fieldValues) {
  138. line.V2 = fieldValues[2-fieldIndex]
  139. }
  140. if fieldIndex <= 3 && 3 < fieldIndex+len(fieldValues) {
  141. line.V3 = fieldValues[3-fieldIndex]
  142. }
  143. if fieldIndex <= 4 && 4 < fieldIndex+len(fieldValues) {
  144. line.V4 = fieldValues[4-fieldIndex]
  145. }
  146. if fieldIndex <= 5 && 5 < fieldIndex+len(fieldValues) {
  147. line.V5 = fieldValues[5-fieldIndex]
  148. }
  149. err := rawDelete(a, line)
  150. return err
  151. }
  152. func loadPolicyLine(line *entity.CasbinRule, model model.Model) {
  153. lineText := line.Ptype
  154. if line.V0 != "" {
  155. lineText += ", " + line.V0
  156. }
  157. if line.V1 != "" {
  158. lineText += ", " + line.V1
  159. }
  160. if line.V2 != "" {
  161. lineText += ", " + line.V2
  162. }
  163. if line.V3 != "" {
  164. lineText += ", " + line.V3
  165. }
  166. if line.V4 != "" {
  167. lineText += ", " + line.V4
  168. }
  169. if line.V5 != "" {
  170. lineText += ", " + line.V5
  171. }
  172. persist.LoadPolicyLine(lineText, model)
  173. }
  174. func savePolicyLine(ptype string, rule []string) *entity.CasbinRule {
  175. line := &entity.CasbinRule{}
  176. line.Ptype = ptype
  177. if len(rule) > 0 {
  178. line.V0 = rule[0]
  179. }
  180. if len(rule) > 1 {
  181. line.V1 = rule[1]
  182. }
  183. if len(rule) > 2 {
  184. line.V2 = rule[2]
  185. }
  186. if len(rule) > 3 {
  187. line.V3 = rule[3]
  188. }
  189. if len(rule) > 4 {
  190. line.V4 = rule[4]
  191. }
  192. if len(rule) > 5 {
  193. line.V5 = rule[5]
  194. }
  195. return line
  196. }
  197. func rawDelete(a *adapterCasbin, line *entity.CasbinRule) error {
  198. db := dao.CasbinRule.Ctx(a.ctx).Where("ptype = ?", line.Ptype)
  199. if line.V0 != "" {
  200. db = db.Where("v0 = ?", line.V0)
  201. }
  202. if line.V1 != "" {
  203. db = db.Where("v1 = ?", line.V1)
  204. }
  205. if line.V2 != "" {
  206. db = db.Where("v2 = ?", line.V2)
  207. }
  208. if line.V3 != "" {
  209. db = db.Where("v3 = ?", line.V3)
  210. }
  211. if line.V4 != "" {
  212. db = db.Where("v4 = ?", line.V4)
  213. }
  214. if line.V5 != "" {
  215. db = db.Where("v5 = ?", line.V5)
  216. }
  217. _, err := db.Delete()
  218. return err
  219. }