package service import ( "errors" "fmt" casbin "github.com/casbin/casbin/v2" "github.com/casbin/casbin/v2/model" gormadapter "github.com/casbin/gorm-adapter/v3" "gorm.io/gorm" ) type ( Auth struct { enforcer *casbin.Enforcer } // Permission 权限信息 Permission struct { request []*AuthRequest // 请求信息 tenant string // 租户信息 roles []string // 角色信息 user string // 用户唯一表示 } // AuthRequest 请求验证 AuthRequest struct { Url string Method string } IdentityPermission func(tenant, user string) *Permission PermissionOptions func(permission *Permission) ) var auth *Auth // adapter 规则 var adapter = map[string]func(params ...interface{}) interface{}{ "mysql": adapterForOrm, "sqlite": adapterForOrm, } // adapterForOrm 规则引擎 func adapterForOrm(params ...interface{}) interface{} { db := params[0].(*gorm.DB) obj := params[1].(string) adapter, _ := gormadapter.NewAdapterByDBUseTableName(db, "", obj) return adapter } func WithAuthRequest(request []*AuthRequest) PermissionOptions { return func(permission *Permission) { permission.request = request } } func WithAuthTenant(tenant string) PermissionOptions { return func(permission *Permission) { permission.tenant = tenant } } func WithAuthRoles(roles []string) PermissionOptions { return func(permission *Permission) { permission.roles = roles } } func WithAuthUser(user string) PermissionOptions { return func(permission *Permission) { permission.user = user } } // Register 注册权限 // 多平台 admin tenant1, data1, read (角色-域-用户-事件) // p admin tenant1, data1, read (角色-域-用户-事件) // g alice, admin, tenant1 (用户-角色-域) func (this *Auth) Register() func(mode string, params ...interface{}) interface{} { return func(mode string, params ...interface{}) interface{} { m := model.NewModel() m.AddDef("r", "r", "sub, dom, obj, act") m.AddDef("p", "p", "sub, dom, obj, act") m.AddDef("g", "g", "_, _, _") m.AddDef("e", "e", "some(where (p.eft == allow))") m.AddDef("m", "m", "g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.act") a, has := adapter[mode] if has { this.enforcer, _ = casbin.NewEnforcer(m, a(params...)) this.enforcer.EnableAutoSave(true) } else { this.enforcer, _ = casbin.NewEnforcer(m) } auth = this return nil } } // tenantFormat 平台信息 func (this *Permission) tenantFormat() string { return fmt.Sprintf("%s%s", "t_", this.tenant) } // userFormat 用户信息 func (this *Permission) userFormat() string { return fmt.Sprintf("%s%s", "u_", this.user) } // roleFormat 角色信息 func (this *Permission) roleFormat() []string { roles := make([]string, 0) for _, v := range this.roles { roles = append(roles, fmt.Sprintf("%s%s", "r_", v)) } return roles } // AddTenant 追加租户 func (this *Permission) AddTenant(tenant string) { this.tenant = tenant } // AddRole 追加角色 func (this *Permission) AddRole(roles []string) { this.roles = roles } // AddUser 追加用户 func (this *Permission) AddUser(user string) { this.user = user } // AddRoleForUser 增加用户角色 func (this *Permission) AddRoleForUser() (bool, error) { if len(this.roles) <= 0 { return false, errors.New("not role") } for _, role := range this.roleFormat() { if _, err := auth.enforcer.AddRoleForUser(this.userFormat(), role, this.tenantFormat()); err != nil { return false, err } } return true, nil } // DeleteRolesForUser 删除用户所有角色 func (this *Permission) DeleteRolesForUser(allTenant bool) (bool, error) { if allTenant { return auth.enforcer.DeleteRolesForUser(this.userFormat()) } return auth.enforcer.DeleteRolesForUser(this.userFormat(), this.tenantFormat()) } // AddPolicies TODO:增加多个规则 func (this *Permission) AddPolicies() (bool, error) { if len(this.request) <= 0 { return false, errors.New("not request") } rules := make([][]string, 0) for _, s := range this.request { rules = append(rules, []string{ this.roleFormat()[0], this.tenantFormat(), s.Url, s.Method, }) } return auth.enforcer.AddPolicies(rules) } // RemoveRolePolicies 删除角色指定规则 func (this *Permission) RemoveRolePolicies() (bool, error) { if len(this.roles) <= 0 { return false, errors.New("not role") } rules := make([][]string, 0) tenantFormat := this.tenantFormat() for _, v := range this.roleFormat() { for _, request := range this.request { rules = append(rules, []string{ v, tenantFormat, request.Url, request.Method, }) } } return auth.enforcer.RemovePolicies(rules) } // RemoveSingleRolePolicy 删除角色的所有规则 func (this *Permission) RemoveSingleRolePolicy() (bool, error) { if len(this.roles) <= 0 { return false, errors.New("not role") } return auth.enforcer.RemoveFilteredPolicy(0, this.roleFormat()[0], this.tenantFormat()) } // RemoveNamedGroupingPolicies 删除租户下角色的权限 func (this *Permission) RemoveNamedGroupingPolicies() (bool, error) { rules := make([][]string, 0) for _, role := range this.roleFormat() { rule := make([]string, 0) for _, request := range this.request { rule = append(rule, role, this.tenantFormat(), request.Url, request.Method) } rules = append(rules, rule) } return auth.enforcer.RemoveNamedGroupingPolicies("g", rules) } // RemoveFilteredGroupingPolicy 删除组权限规则 func (this *Permission) RemoveFilteredGroupingPolicy() (bool, error) { return auth.enforcer.RemoveFilteredGroupingPolicy(0, this.tenantFormat()) } // Enforce 检查访问权限 func (this *Permission) Enforce() (bool, error) { if len(this.request) <= 0 { return false, errors.New("not request") } return auth.enforcer.Enforce(this.userFormat(), this.tenantFormat(), this.request[0].Url, "*") } // NewAuth 创建验证 func NewAuth() *Auth { return &Auth{} } // NewPermission 创建权限 func NewPermission(options ...PermissionOptions) *Permission { out := new(Permission) for _, option := range options { option(out) } return out }