mirror of
https://github.com/quarkcloudio/quark-go.git
synced 2025-09-26 20:11:11 +08:00
347 lines
7.4 KiB
Go
347 lines
7.4 KiB
Go
package model
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/casbin/casbin/v2"
|
|
casbinmodel "github.com/casbin/casbin/v2/model"
|
|
gormadapter "github.com/casbin/gorm-adapter/v3"
|
|
rediswatcher "github.com/casbin/redis-watcher/v2"
|
|
"github.com/quarkcloudio/quark-go/v2/pkg/builder"
|
|
"github.com/quarkcloudio/quark-go/v2/pkg/dal/db"
|
|
"github.com/redis/go-redis/v9"
|
|
)
|
|
|
|
// 字段
|
|
type CasbinRule struct {
|
|
ID uint `gorm:"primaryKey;autoIncrement"`
|
|
Ptype string `gorm:"size:100;uniqueIndex:unique_index"`
|
|
V0 string `gorm:"size:100;uniqueIndex:unique_index"`
|
|
V1 string `gorm:"size:100;uniqueIndex:unique_index"`
|
|
V2 string `gorm:"size:100;uniqueIndex:unique_index"`
|
|
V3 string `gorm:"size:100;uniqueIndex:unique_index"`
|
|
V4 string `gorm:"size:100;uniqueIndex:unique_index"`
|
|
V5 string `gorm:"size:100;uniqueIndex:unique_index"`
|
|
}
|
|
|
|
var Enforcer *casbin.Enforcer
|
|
|
|
// 获取Enforcer
|
|
func (p *CasbinRule) Enforcer() (enforcer *casbin.Enforcer, err error) {
|
|
if Enforcer != nil {
|
|
return Enforcer, err
|
|
}
|
|
|
|
a, err := gormadapter.NewAdapterByDBWithCustomTable(db.Client, &CasbinRule{}, "casbin_rules")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
m, err := casbinmodel.NewModelFromString(`
|
|
[request_definition]
|
|
r = sub, obj, act
|
|
|
|
[policy_definition]
|
|
p = sub, obj, act
|
|
|
|
[role_definition]
|
|
g = _, _
|
|
|
|
[policy_effect]
|
|
e = some(where (p.eft == allow))
|
|
|
|
[matchers]
|
|
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
|
|
`)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
Enforcer, err = casbin.NewEnforcer(m, a)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
redisConfig := builder.GetConfig().RedisConfig
|
|
if redisConfig != nil {
|
|
w, _ := rediswatcher.NewWatcher(redisConfig.Host+":"+redisConfig.Port, rediswatcher.WatcherOptions{
|
|
Options: redis.Options{
|
|
Network: "tcp",
|
|
Password: redisConfig.Password,
|
|
},
|
|
})
|
|
|
|
// Set the watcher for the enforcer.
|
|
err = Enforcer.SetWatcher(w)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Or use the default callback
|
|
err = w.SetUpdateCallback(rediswatcher.DefaultUpdateCallback(Enforcer))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return Enforcer, err
|
|
}
|
|
|
|
// 查看是否放行
|
|
func (p *CasbinRule) Enforce(sub string, obj string, act string) (result bool, err error) {
|
|
enforcer, err := p.Enforcer()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
result, err = enforcer.Enforce(sub, obj, act)
|
|
|
|
return
|
|
}
|
|
|
|
// 添加菜单拥有的权限
|
|
func (p *CasbinRule) AddMenuPermission(menuId int, permissionIds interface{}) (err error) {
|
|
enforcer, err := p.Enforcer()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
permissions, err := (&Permission{}).GetListByIds(permissionIds)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rules := [][]string{}
|
|
for _, v := range permissions {
|
|
rules = append(rules, []string{"menu|" + strconv.Itoa(menuId), v.Name, "MenuHasPermission"})
|
|
}
|
|
|
|
p.RemoveMenuPermissions(menuId)
|
|
if len(rules) == 0 {
|
|
return
|
|
}
|
|
|
|
_, err = enforcer.AddPolicies(rules)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
enforcer.SavePolicy()
|
|
|
|
return
|
|
}
|
|
|
|
// 删除菜单拥有的权限
|
|
func (p *CasbinRule) RemoveMenuPermissions(menuId int) (err error) {
|
|
enforcer, err := p.Enforcer()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = enforcer.DeleteUser("menu|" + strconv.Itoa(menuId))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
enforcer.SavePolicy()
|
|
|
|
return
|
|
}
|
|
|
|
// 获取菜单拥有的权限
|
|
func (p *CasbinRule) GetMenuPermissions(menuId int) (permissions []*Permission, err error) {
|
|
enforcer, err := p.Enforcer()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
permissionNames := []string{}
|
|
menuHasPermissions := enforcer.GetPermissionsForUser("menu|" + strconv.Itoa(menuId))
|
|
for _, v := range menuHasPermissions {
|
|
permissionNames = append(permissionNames, v[1])
|
|
}
|
|
|
|
permissions, err = (&Permission{}).GetListByNames(permissionNames)
|
|
|
|
return
|
|
}
|
|
|
|
// 给角色添加菜单及权限
|
|
func (p *CasbinRule) AddMenuAndPermissionToRole(roleId int, menuIds []int) (err error) {
|
|
enforcer, err := p.Enforcer()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rules := [][]string{}
|
|
|
|
// 角色拥有的菜单
|
|
for _, v := range menuIds {
|
|
rules = append(rules, []string{"role|" + strconv.Itoa(roleId), "menu|" + strconv.Itoa(v), "RoleHasMenu"})
|
|
}
|
|
|
|
// 角色拥有的权限
|
|
for _, v := range menuIds {
|
|
menuHasPermissions, err := p.GetMenuPermissions(v)
|
|
if err == nil {
|
|
for _, sv := range menuHasPermissions {
|
|
rules = append(rules, []string{"role|" + strconv.Itoa(roleId), sv.Path, sv.Method})
|
|
}
|
|
}
|
|
}
|
|
|
|
// 先清理数据
|
|
p.RemoveRoleMenuAndPermissions(roleId)
|
|
|
|
if len(rules) > 0 {
|
|
// 添加策略
|
|
_, err = enforcer.AddPolicies(rules)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 删除角色拥有的菜单及权限
|
|
func (p *CasbinRule) RemoveRoleMenuAndPermissions(roleId int) (err error) {
|
|
enforcer, err := p.Enforcer()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = enforcer.DeleteUser("role|" + strconv.Itoa(roleId))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 获取角色拥有的菜单
|
|
func (p *CasbinRule) GetRoleMenus(roleId int) (menus []*Menu, err error) {
|
|
enforcer, err := p.Enforcer()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
menuIds := []interface{}{}
|
|
roleHasPermissions := enforcer.GetPermissionsForUser("role|" + strconv.Itoa(roleId))
|
|
for _, v := range roleHasPermissions {
|
|
if v[2] == "RoleHasMenu" {
|
|
menuIdArr := strings.Split(v[1], "|")
|
|
if len(menuIdArr) > 1 {
|
|
menuIds = append(menuIds, menuIdArr[1])
|
|
}
|
|
}
|
|
}
|
|
menus, err = (&Menu{}).GetListByIds(menuIds)
|
|
|
|
return
|
|
}
|
|
|
|
// 获取角色拥有的权限
|
|
func (p *CasbinRule) GetRolePermissions(roleId int) (permissions []*Permission, err error) {
|
|
enforcer, err := p.Enforcer()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
permissionNames := []string{}
|
|
roleHasPermissions := enforcer.GetPermissionsForUser("role|" + strconv.Itoa(roleId))
|
|
for _, v := range roleHasPermissions {
|
|
if v[2] != "RoleHasMenu" {
|
|
permissionNames = append(permissionNames, v[1])
|
|
}
|
|
}
|
|
permissions, err = (&Permission{}).GetListByNames(permissionNames)
|
|
|
|
return
|
|
}
|
|
|
|
// 添加用户拥有的角色
|
|
func (p *CasbinRule) AddUserRole(modelId int, roleIds []int) (err error) {
|
|
enforcer, err := p.Enforcer()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
roles := []string{}
|
|
for _, v := range roleIds {
|
|
roles = append(roles, "role|"+strconv.Itoa(v))
|
|
}
|
|
|
|
p.RemoveUserRoles(modelId)
|
|
|
|
if len(roles) > 0 {
|
|
_, err = enforcer.AddRolesForUser("admin|"+strconv.Itoa(modelId), roles)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 删除用户拥有的角色
|
|
func (p *CasbinRule) RemoveUserRoles(modelId int) (err error) {
|
|
enforcer, err := p.Enforcer()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = enforcer.DeleteRolesForUser("admin|" + strconv.Itoa(modelId))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 获取用户拥有的角色
|
|
func (p *CasbinRule) GetUserRoles(modelId int) (roles []*Role, err error) {
|
|
enforcer, err := p.Enforcer()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
roleStrIds, err := enforcer.GetRolesForUser("admin|" + strconv.Itoa(modelId))
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
roleIds := []interface{}{}
|
|
for _, v := range roleStrIds {
|
|
roleIdArr := strings.Split(v, "|")
|
|
if len(roleIdArr) > 1 {
|
|
roleIds = append(roleIds, roleIdArr[1])
|
|
}
|
|
}
|
|
roles, err = (&Role{}).GetListByIds(roleIds)
|
|
|
|
return
|
|
}
|
|
|
|
// 获取用户拥有的菜单
|
|
func (p *CasbinRule) GetUserMenus(modelId int) (menus []*Menu, err error) {
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
getMenus := []*Menu{}
|
|
roles, err := p.GetUserRoles(modelId)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
for _, v := range roles {
|
|
roleMenus, err := p.GetRoleMenus(v.Id)
|
|
if err == nil {
|
|
getMenus = append(getMenus, roleMenus...)
|
|
}
|
|
}
|
|
|
|
return getMenus, nil
|
|
}
|