diff --git a/apps/system/api/api.go b/apps/system/api/api.go index b96b005..8694175 100644 --- a/apps/system/api/api.go +++ b/apps/system/api/api.go @@ -1,12 +1,12 @@ package api import ( - "github.com/PandaXGO/PandaKit/casbin" - "github.com/PandaXGO/PandaKit/model" - "github.com/PandaXGO/PandaKit/restfulx" - "github.com/PandaXGO/PandaKit/utils" entity "pandax/apps/system/entity" services "pandax/apps/system/services" + "pandax/kit/casbin" + "pandax/kit/model" + "pandax/kit/restfulx" + "pandax/kit/utils" "pandax/pkg/global" ) @@ -60,6 +60,6 @@ func (s *SystemApiApi) GetAllApis(rc *restfulx.ReqCtx) { func (s *SystemApiApi) GetPolicyPathByRoleId(rc *restfulx.ReqCtx) { roleKey := rc.Request.QueryParameter("roleKey") - ca := casbin.CasbinS{ModelPath: global.Conf.Casbin.ModelPath} + ca := casbin.CasbinService{ModelPath: global.Conf.Casbin.ModelPath} rc.ResData = ca.GetPolicyPathByRoleId(roleKey) } diff --git a/apps/system/api/role.go b/apps/system/api/role.go index 306baab..3547c6b 100644 --- a/apps/system/api/role.go +++ b/apps/system/api/role.go @@ -3,13 +3,13 @@ package api import ( "errors" "fmt" - "github.com/PandaXGO/PandaKit/biz" - "github.com/PandaXGO/PandaKit/casbin" - "github.com/PandaXGO/PandaKit/model" - "github.com/PandaXGO/PandaKit/restfulx" - "github.com/PandaXGO/PandaKit/utils" entity "pandax/apps/system/entity" services "pandax/apps/system/services" + "pandax/kit/biz" + "pandax/kit/casbin" + "pandax/kit/model" + "pandax/kit/restfulx" + "pandax/kit/utils" "pandax/pkg/global" ) @@ -61,7 +61,7 @@ func (r *RoleApi) InsertRole(rc *restfulx.ReqCtx) { role.RoleId = insert.RoleId r.RoleMenuApp.Insert(insert.RoleId, role.MenuIds) //添加权限 - ca := casbin.CasbinS{ModelPath: global.Conf.Casbin.ModelPath} + ca := casbin.CasbinService{ModelPath: global.Conf.Casbin.ModelPath} ca.UpdateCasbin(role.RoleKey, role.ApiIds) } @@ -77,7 +77,7 @@ func (r *RoleApi) UpdateRole(rc *restfulx.ReqCtx) { // 添加角色菜单绑定 r.RoleMenuApp.Insert(role.RoleId, role.MenuIds) //修改api权限 - ca := casbin.CasbinS{ModelPath: global.Conf.Casbin.ModelPath} + ca := casbin.CasbinService{ModelPath: global.Conf.Casbin.ModelPath} ca.UpdateCasbin(role.RoleKey, role.ApiIds) } @@ -139,7 +139,7 @@ func (r *RoleApi) DeleteRole(rc *restfulx.ReqCtx) { if len(*list) == 0 { delList = append(delList, rid) //删除角色绑定api - ca := casbin.CasbinS{ModelPath: global.Conf.Casbin.ModelPath} + ca := casbin.CasbinService{ModelPath: global.Conf.Casbin.ModelPath} ca.ClearCasbin(0, role.RoleKey) } else { global.Log.Info(fmt.Sprintf("role:%d 存在用户无法删除", rid)) diff --git a/apps/system/services/api.go b/apps/system/services/api.go index ec7197f..b17e97d 100644 --- a/apps/system/services/api.go +++ b/apps/system/services/api.go @@ -2,11 +2,12 @@ package services import ( "errors" - "github.com/PandaXGO/PandaKit/biz" - "github.com/PandaXGO/PandaKit/casbin" - "gorm.io/gorm" "pandax/apps/system/entity" + "pandax/kit/biz" + "pandax/kit/casbin" "pandax/pkg/global" + + "gorm.io/gorm" ) type ( @@ -107,7 +108,7 @@ func (m *sysApiModelImpl) Update(api entity.SysApi) *entity.SysApi { biz.IsTrue(errors.Is(err, gorm.ErrRecordNotFound), "存在相同api路径") } // 异常直接抛错误 - ca := casbin.CasbinS{ModelPath: global.Conf.Casbin.ModelPath} + ca := casbin.CasbinService{ModelPath: global.Conf.Casbin.ModelPath} ca.UpdateCasbinApi(oldA.Path, api.Path, oldA.Method, api.Method) err = global.Db.Table(m.table).Model(&api).Updates(&api).Error biz.ErrIsNil(err, "修改api信息失败") diff --git a/kit/casbin/casbin.go b/kit/casbin/casbin.go new file mode 100644 index 0000000..0f5c7b3 --- /dev/null +++ b/kit/casbin/casbin.go @@ -0,0 +1,81 @@ +package casbin + +import ( + "pandax/kit/biz" + "pandax/kit/starter" + "sync" + + "github.com/casbin/casbin/v2" + gormadapter "github.com/casbin/gorm-adapter/v3" +) + +type CasbinService struct { + ModelPath string +} + +func (c *CasbinService) UpdateCasbin(roleKey string, casbinInfos []CasbinRule) error { + c.ClearCasbin(0, roleKey) + rules := [][]string{} + for _, v := range casbinInfos { + rules = append(rules, []string{roleKey, v.Path, v.Method}) + } + e := c.GetCasbinEnforcer() + success, err := e.AddPolicies(rules) + if err != nil { + return err + } + if !success { + return biz.NewBizErr("存在相同api,添加失败,请联系管理员") + } + return nil +} + +func (c *CasbinService) UpdateCasbinApi(oldPath string, newPath string, oldMethod string, newMethod string) error { + err := starter.Db.Table("casbin_rule").Model(&CasbinRule{}).Where("v1 = ? AND v2 = ?", oldPath, oldMethod).Updates(map[string]interface{}{ + "v1": newPath, + "v2": newMethod, + }).Error + if err != nil { + return biz.NewBizErr("修改api失败") + } + return nil +} + +func (c *CasbinService) GetPolicyPathByRoleId(roleKey string) []CasbinRule { + e := c.GetCasbinEnforcer() + list := e.GetFilteredPolicy(0, roleKey) + pathMaps := make([]CasbinRule, len(list)) + for i, v := range list { + pathMaps[i] = CasbinRule{ + Path: v[1], + Method: v[2], + } + } + return pathMaps +} + +func (c *CasbinService) ClearCasbin(v int, p ...string) bool { + e := c.GetCasbinEnforcer() + success, _ := e.RemoveFilteredPolicy(v, p...) + return success +} + +var ( + syncedEnforcer *casbin.SyncedEnforcer + once sync.Once +) + +func (c *CasbinService) GetCasbinEnforcer() *casbin.SyncedEnforcer { + once.Do(func() { + a, err := gormadapter.NewAdapterByDB(starter.Db) + if err != nil { + panic(biz.NewBizErr("新建权限适配器失败")) + } + syncedEnforcer, err = casbin.NewSyncedEnforcer(c.ModelPath, a) + if err != nil { + panic(biz.NewBizErr("新建权限适配器失败")) + } + }) + _ = syncedEnforcer.LoadPolicy() + return syncedEnforcer +} diff --git a/kit/casbin/casbin_model.go b/kit/casbin/casbin_model.go new file mode 100644 index 0000000..6bdf48f --- /dev/null +++ b/kit/casbin/casbin_model.go @@ -0,0 +1,16 @@ +package casbin + +type CasbinRule struct { + Ptype string `json:"ptype" gorm:"column:ptype"` + RoleKey string `json:"roleKey" gorm:"column:v0"` + Path string `json:"path" gorm:"column:v1"` + Method string `json:"method" gorm:"column:v2"` + V3 string `json:"v3" gorm:"column:v3"` + V4 string `json:"v4" gorm:"column:v4"` + V5 string `json:"v5" gorm:"column:v5"` + Id int `json:"id" gorm:"primary_key;AUTO_INCREMENT;column:id"` +} + +func (CasbinRule) TableName() string { + return "casbin_rule" +} diff --git a/pkg/middleware/permission.go b/pkg/middleware/permission.go index 8c71da1..fd784d5 100644 --- a/pkg/middleware/permission.go +++ b/pkg/middleware/permission.go @@ -1,12 +1,13 @@ package middleware import ( - "github.com/PandaXGO/PandaKit/biz" - "github.com/PandaXGO/PandaKit/casbin" - "github.com/PandaXGO/PandaKit/restfulx" - "github.com/PandaXGO/PandaKit/token" - "github.com/dgrijalva/jwt-go" + "pandax/kit/biz" + "pandax/kit/casbin" + "pandax/kit/restfulx" + "pandax/kit/token" "pandax/pkg/global" + + "github.com/dgrijalva/jwt-go" ) func PermissionHandler(rc *restfulx.ReqCtx) error { @@ -34,11 +35,11 @@ func PermissionHandler(rc *restfulx.ReqCtx) error { return nil } - ca := casbin.CasbinS{ModelPath: global.Conf.Casbin.ModelPath} - e := ca.Casbin() + ca := casbin.CasbinService{ModelPath: global.Conf.Casbin.ModelPath} + e := ca.GetCasbinEnforcer() // 判断策略中是否存在 success, err := e.Enforce(loginAccount.RoleKey, rc.Request.Request.URL.Path, rc.Request.Request.Method) - if !success { + if !success || err != nil { return biz.CasbinErr }