package mycasbin import ( "errors" "fmt" "github.com/casbin/casbin/v2" "github.com/casbin/casbin/v2/model" "github.com/casbin/casbin/v2/util" "gorm.io/gorm" "net/http" ) // Model语法 https://casbin.org/docs/zh-CN/syntax-for-models // sub, obj, act 表示经典三元组: 访问实体 (Subject),访问资源 (Object) 和访问方法 (Action)。 // sub:希望访问资源的用户 // dom:域/域租户 https://casbin.org/docs/zh-CN/rbac-with-domains // obj:要访问的资源 // act:用户对资源执行的操作 var text = ` [request_definition] r = sub, dom, obj, act [policy_definition] p = sub, dom, obj, act [role_definition] g = _, _, _ [policy_effect] e = some(where (p.eft == allow)) [matchers] 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" ` // 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") //m = r.sub == p.sub && (keyMatch2(r.obj, p.obj) || keyMatch(r.obj, p.obj)) && (r.act == p.act || p.act == "*") func Setup(db *gorm.DB) *casbin.SyncedEnforcer { Apter, err := NewAdapterByDB(db) if err != nil { panic(err) } m, err := model.NewModelFromString(text) if err != nil { panic(err) } e, err := casbin.NewSyncedEnforcer(m, Apter) if err != nil { panic(err) } err = e.LoadPolicy() if err != nil { panic(err) } //e.StartAutoLoadPolicy(time.Minute) //e.AddFunction("MyDomKeyMatch2", MyDomKeyMatch2Func) //e.AddFunction("MyRegexMatch", MyRegexMatchFunc) e.EnableLog(true) return e } // validate the variadic parameter size and type as string func validateVariadicArgs(expectedLen int, args ...interface{}) error { if len(args) != expectedLen { return fmt.Errorf("Expected %d arguments, but got %d", expectedLen, len(args)) } for _, p := range args { _, ok := p.(string) if !ok { return errors.New("Argument must be a string") } } return nil } // MyDomKeyMatch2Func 定义域KeyMatch2 func MyDomKeyMatch2Func(args ...interface{}) (interface{}, error) { if err := validateVariadicArgs(4, args...); err != nil { return false,fmt.Errorf("%s: %s", "keyMatch2", err) } name1 := args[0].(string) name2 := args[1].(string) dom1 := args[2].(string) dom2 := args[3].(string) return (bool)(dom1 == dom2 && util.KeyMatch2(name1, name2)),nil } // MyRegexMatchFunc 定义域RegexMatch func MyRegexMatchFunc(args ...interface{}) (interface{}, error) { if err := validateVariadicArgs(4, args...); err != nil { return false, fmt.Errorf("%s: %s", "RegexMatch", err) } name1 := args[0].(string) name2 := args[1].(string) dom1 := args[2].(string) dom2 := args[3].(string) return (bool)(dom1 == dom2 && util.RegexMatch(name1, name2)),nil } // EnforceRoute 验证web路由 func EnforceRoute(roleKey, serviceID string, req *http.Request, enforcer casbin.IEnforcer) (bool, error) { sub := fmt.Sprintf("role:%s", roleKey) // 希望访问资源的用户 dom := fmt.Sprintf("service:%s:api", serviceID) // 域/域租户,这里以资源为单位 obj := req.URL.Path // 要访问的资源 act := req.Method // 用户对资源执行的操作 return enforcer.Enforce(sub, dom, obj, act) } // EnforceRouteForScopeCode 验证web路由 func EnforceRouteForScopeCode(roleKey, serviceID string, req *http.Request, enforcer casbin.IEnforcer) (bool, error) { sub := fmt.Sprintf("scope:%s", roleKey) // 希望访问资源的用户 dom := fmt.Sprintf("service:%s:api", serviceID) // 域/域租户,这里以资源为单位 obj := req.URL.Path // 要访问的资源 act := req.Method // 用户对资源执行的操作 return enforcer.Enforce(sub, dom, obj, act) }