mycasbin.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package mycasbin
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/casbin/casbin/v2"
  6. "github.com/casbin/casbin/v2/model"
  7. "github.com/casbin/casbin/v2/util"
  8. "gorm.io/gorm"
  9. "net/http"
  10. )
  11. // Model语法 https://casbin.org/docs/zh-CN/syntax-for-models
  12. // sub, obj, act 表示经典三元组: 访问实体 (Subject),访问资源 (Object) 和访问方法 (Action)。
  13. // sub:希望访问资源的用户
  14. // dom:域/域租户 https://casbin.org/docs/zh-CN/rbac-with-domains
  15. // obj:要访问的资源
  16. // act:用户对资源执行的操作
  17. var text = `
  18. [request_definition]
  19. r = sub, dom, obj, act
  20. [policy_definition]
  21. p = sub, dom, obj, act
  22. [role_definition]
  23. g = _, _, _
  24. [policy_effect]
  25. e = some(where (p.eft == allow))
  26. [matchers]
  27. m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && (keyMatch2(r.obj, p.obj) || keyMatch(r.obj, p.obj)) && r.act == p.act || r.sub == "role:admin"
  28. `
  29. // m = g(r.sub, p.sub, r.dom) && MyDomKeyMatch2(r.obj, p.obj, r.dom, p.dom) && MyRegexMatch(r.act, p.act, r.dom, p.dom) || r.sub == "role:admin")
  30. //m = r.sub == p.sub && (keyMatch2(r.obj, p.obj) || keyMatch(r.obj, p.obj)) && (r.act == p.act || p.act == "*")
  31. func Setup(db *gorm.DB) *casbin.SyncedEnforcer {
  32. Apter, err := NewAdapterByDB(db)
  33. if err != nil {
  34. panic(err)
  35. }
  36. m, err := model.NewModelFromString(text)
  37. if err != nil {
  38. panic(err)
  39. }
  40. e, err := casbin.NewSyncedEnforcer(m, Apter)
  41. if err != nil {
  42. panic(err)
  43. }
  44. err = e.LoadPolicy()
  45. if err != nil {
  46. panic(err)
  47. }
  48. //e.StartAutoLoadPolicy(time.Minute)
  49. //e.AddFunction("MyDomKeyMatch2", MyDomKeyMatch2Func)
  50. //e.AddFunction("MyRegexMatch", MyRegexMatchFunc)
  51. e.EnableLog(true)
  52. return e
  53. }
  54. // validate the variadic parameter size and type as string
  55. func validateVariadicArgs(expectedLen int, args ...interface{}) error {
  56. if len(args) != expectedLen {
  57. return fmt.Errorf("Expected %d arguments, but got %d", expectedLen, len(args))
  58. }
  59. for _, p := range args {
  60. _, ok := p.(string)
  61. if !ok {
  62. return errors.New("Argument must be a string")
  63. }
  64. }
  65. return nil
  66. }
  67. // MyDomKeyMatch2Func 定义域KeyMatch2
  68. func MyDomKeyMatch2Func(args ...interface{}) (interface{}, error) {
  69. if err := validateVariadicArgs(4, args...); err != nil {
  70. return false,fmt.Errorf("%s: %s", "keyMatch2", err)
  71. }
  72. name1 := args[0].(string)
  73. name2 := args[1].(string)
  74. dom1 := args[2].(string)
  75. dom2 := args[3].(string)
  76. return (bool)(dom1 == dom2 && util.KeyMatch2(name1, name2)),nil
  77. }
  78. // MyRegexMatchFunc 定义域RegexMatch
  79. func MyRegexMatchFunc(args ...interface{}) (interface{}, error) {
  80. if err := validateVariadicArgs(4, args...); err != nil {
  81. return false, fmt.Errorf("%s: %s", "RegexMatch", err)
  82. }
  83. name1 := args[0].(string)
  84. name2 := args[1].(string)
  85. dom1 := args[2].(string)
  86. dom2 := args[3].(string)
  87. return (bool)(dom1 == dom2 && util.RegexMatch(name1, name2)),nil
  88. }
  89. // EnforceRoute 验证web路由
  90. func EnforceRoute(roleKey, serviceID string, req *http.Request, enforcer casbin.IEnforcer) (bool, error) {
  91. sub := fmt.Sprintf("role:%s", roleKey) // 希望访问资源的用户
  92. dom := fmt.Sprintf("service:%s:api", serviceID) // 域/域租户,这里以资源为单位
  93. obj := req.URL.Path // 要访问的资源
  94. act := req.Method // 用户对资源执行的操作
  95. return enforcer.Enforce(sub, dom, obj, act)
  96. }
  97. // EnforceRouteForScopeCode 验证web路由
  98. func EnforceRouteForScopeCode(roleKey, serviceID string, req *http.Request, enforcer casbin.IEnforcer) (bool, error) {
  99. sub := fmt.Sprintf("scope:%s", roleKey) // 希望访问资源的用户
  100. dom := fmt.Sprintf("service:%s:api", serviceID) // 域/域租户,这里以资源为单位
  101. obj := req.URL.Path // 要访问的资源
  102. act := req.Method // 用户对资源执行的操作
  103. return enforcer.Enforce(sub, dom, obj, act)
  104. }