- 开始添加casbin做角色,权限管理
This commit is contained in:
10
business/authz/authz.go
Normal file
10
business/authz/authz.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package authz
|
||||||
|
|
||||||
|
type IAuthz interface {
|
||||||
|
AddStoreRole4User(userID string, storeID int) (err error)
|
||||||
|
DelStoreRole4User(userID string, storeID int) (err error)
|
||||||
|
AddRole4User(userID, roleName string) (err error)
|
||||||
|
DelRole4User(userID, roleName string) (err error)
|
||||||
|
GetUserRoleList(userID string) (roleList []string, err error)
|
||||||
|
GetRoleUserList(roleName string) (userIDList []string, err error)
|
||||||
|
}
|
||||||
29
business/authz/authz_utils.go
Normal file
29
business/authz/authz_utils.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package authz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
RoleNameSep = "/"
|
||||||
|
RolePrefix = "role"
|
||||||
|
StoreRolePrefix = "store"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GenStoreRoleName(storeID int) (roleName string) {
|
||||||
|
return strings.Join([]string{
|
||||||
|
RolePrefix,
|
||||||
|
StoreRolePrefix,
|
||||||
|
utils.Int2Str(storeID),
|
||||||
|
}, RoleNameSep)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetStoreIDFromRole(roleName string) (storeID int) {
|
||||||
|
list := strings.Split(roleName, RoleNameSep)
|
||||||
|
if len(list) == 3 {
|
||||||
|
storeID = int(utils.Str2Int64WithDefault(list[2], 0))
|
||||||
|
}
|
||||||
|
return storeID
|
||||||
|
}
|
||||||
185
business/authz/casbinauth/adapter.go
Normal file
185
business/authz/casbinauth/adapter.go
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
package casbinauth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.rosy.net.cn/jx-callback/globals"
|
||||||
|
"github.com/astaxie/beego/orm"
|
||||||
|
"github.com/casbin/casbin/model"
|
||||||
|
"github.com/casbin/casbin/persist"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CasbinRule struct {
|
||||||
|
ID int `orm:"column(id)" json:"id"`
|
||||||
|
PType string
|
||||||
|
V0 string
|
||||||
|
V1 string
|
||||||
|
V2 string
|
||||||
|
V3 string
|
||||||
|
V4 string
|
||||||
|
V5 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Adapter struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterModel() {
|
||||||
|
orm.RegisterModel(new(CasbinRule))
|
||||||
|
}
|
||||||
|
|
||||||
|
// finalizer is the destructor for Adapter.
|
||||||
|
func finalizer(a *Adapter) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAdapter() *Adapter {
|
||||||
|
return &Adapter{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadPolicyLine(line CasbinRule, model model.Model) {
|
||||||
|
lineText := line.PType
|
||||||
|
if line.V0 != "" {
|
||||||
|
lineText += ", " + line.V0
|
||||||
|
}
|
||||||
|
if line.V1 != "" {
|
||||||
|
lineText += ", " + line.V1
|
||||||
|
}
|
||||||
|
if line.V2 != "" {
|
||||||
|
lineText += ", " + line.V2
|
||||||
|
}
|
||||||
|
if line.V3 != "" {
|
||||||
|
lineText += ", " + line.V3
|
||||||
|
}
|
||||||
|
if line.V4 != "" {
|
||||||
|
lineText += ", " + line.V4
|
||||||
|
}
|
||||||
|
if line.V5 != "" {
|
||||||
|
lineText += ", " + line.V5
|
||||||
|
}
|
||||||
|
|
||||||
|
persist.LoadPolicyLine(lineText, model)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Adapter) LoadPolicy(model model.Model) error {
|
||||||
|
var lines []CasbinRule
|
||||||
|
o := orm.NewOrm()
|
||||||
|
_, err := o.QueryTable("casbin_rule").Limit(-1).All(&lines)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
loadPolicyLine(line, model)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func savePolicyLine(ptype string, rule []string) CasbinRule {
|
||||||
|
line := CasbinRule{}
|
||||||
|
|
||||||
|
line.PType = ptype
|
||||||
|
if len(rule) > 0 {
|
||||||
|
line.V0 = rule[0]
|
||||||
|
}
|
||||||
|
if len(rule) > 1 {
|
||||||
|
line.V1 = rule[1]
|
||||||
|
}
|
||||||
|
if len(rule) > 2 {
|
||||||
|
line.V2 = rule[2]
|
||||||
|
}
|
||||||
|
if len(rule) > 3 {
|
||||||
|
line.V3 = rule[3]
|
||||||
|
}
|
||||||
|
if len(rule) > 4 {
|
||||||
|
line.V4 = rule[4]
|
||||||
|
}
|
||||||
|
if len(rule) > 5 {
|
||||||
|
line.V5 = rule[5]
|
||||||
|
}
|
||||||
|
|
||||||
|
return line
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Adapter) clearAll(o orm.Ormer) (err error) {
|
||||||
|
_, err = o.Raw(`
|
||||||
|
DELETE t1
|
||||||
|
FROM casbin_rule t1
|
||||||
|
`).Exec()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SavePolicy saves policy to database.
|
||||||
|
func (a *Adapter) SavePolicy(model model.Model) error {
|
||||||
|
globals.SugarLogger.Debugf("SavePolicy")
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
a.clearAll(o)
|
||||||
|
var lines []CasbinRule
|
||||||
|
|
||||||
|
for ptype, ast := range model["p"] {
|
||||||
|
for _, rule := range ast.Policy {
|
||||||
|
line := savePolicyLine(ptype, rule)
|
||||||
|
lines = append(lines, line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ptype, ast := range model["g"] {
|
||||||
|
for _, rule := range ast.Policy {
|
||||||
|
line := savePolicyLine(ptype, rule)
|
||||||
|
lines = append(lines, line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := o.InsertMulti(len(lines), lines)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddPolicy adds a policy rule to the storage.
|
||||||
|
func (a *Adapter) AddPolicy(sec string, ptype string, rule []string) error {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
line := savePolicyLine(ptype, rule)
|
||||||
|
_, err := o.Insert(&line)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemovePolicy removes a policy rule from the storage.
|
||||||
|
func (a *Adapter) RemovePolicy(sec string, ptype string, rule []string) error {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
line := savePolicyLine(ptype, rule)
|
||||||
|
_, err := o.Delete(&line, "p_type", "v0", "v1", "v2", "v3", "v4", "v5")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveFilteredPolicy removes policy rules that match the filter from the storage.
|
||||||
|
func (a *Adapter) RemoveFilteredPolicy(sec string, ptype string, fieldIndex int, fieldValues ...string) error {
|
||||||
|
line := CasbinRule{}
|
||||||
|
|
||||||
|
line.PType = ptype
|
||||||
|
filter := []string{}
|
||||||
|
filter = append(filter, "p_type")
|
||||||
|
if fieldIndex <= 0 && 0 < fieldIndex+len(fieldValues) {
|
||||||
|
line.V0 = fieldValues[0-fieldIndex]
|
||||||
|
filter = append(filter, "v0")
|
||||||
|
}
|
||||||
|
if fieldIndex <= 1 && 1 < fieldIndex+len(fieldValues) {
|
||||||
|
line.V1 = fieldValues[1-fieldIndex]
|
||||||
|
filter = append(filter, "v1")
|
||||||
|
}
|
||||||
|
if fieldIndex <= 2 && 2 < fieldIndex+len(fieldValues) {
|
||||||
|
line.V2 = fieldValues[2-fieldIndex]
|
||||||
|
filter = append(filter, "v2")
|
||||||
|
}
|
||||||
|
if fieldIndex <= 3 && 3 < fieldIndex+len(fieldValues) {
|
||||||
|
line.V3 = fieldValues[3-fieldIndex]
|
||||||
|
filter = append(filter, "v3")
|
||||||
|
}
|
||||||
|
if fieldIndex <= 4 && 4 < fieldIndex+len(fieldValues) {
|
||||||
|
line.V4 = fieldValues[4-fieldIndex]
|
||||||
|
filter = append(filter, "v4")
|
||||||
|
}
|
||||||
|
if fieldIndex <= 5 && 5 < fieldIndex+len(fieldValues) {
|
||||||
|
line.V5 = fieldValues[5-fieldIndex]
|
||||||
|
filter = append(filter, "v5")
|
||||||
|
}
|
||||||
|
|
||||||
|
o := orm.NewOrm()
|
||||||
|
_, err := o.Delete(&line, filter...)
|
||||||
|
return err
|
||||||
|
}
|
||||||
44
business/authz/casbinauth/casbinauth.go
Normal file
44
business/authz/casbinauth/casbinauth.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package casbinauth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.rosy.net.cn/jx-callback/business/authz"
|
||||||
|
"github.com/casbin/casbin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CasbinAuthz struct {
|
||||||
|
enforcer *casbin.SyncedEnforcer
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(modelFile string) (authObj authz.IAuthz, err error) {
|
||||||
|
obj := &CasbinAuthz{}
|
||||||
|
obj.enforcer, err = casbin.NewSyncedEnforcer(modelFile, NewAdapter())
|
||||||
|
return obj, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CasbinAuthz) AddStoreRole4User(userID string, storeID int) (err error) {
|
||||||
|
return c.AddRole4User(userID, authz.GenStoreRoleName(storeID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CasbinAuthz) DelStoreRole4User(userID string, storeID int) (err error) {
|
||||||
|
return c.DelRole4User(userID, authz.GenStoreRoleName(storeID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CasbinAuthz) AddRole4User(userID, roleName string) (err error) {
|
||||||
|
_, err = c.enforcer.AddRoleForUser(userID, roleName)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CasbinAuthz) DelRole4User(userID, roleName string) (err error) {
|
||||||
|
_, err = c.enforcer.DeleteRoleForUser(userID, roleName)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CasbinAuthz) GetUserRoleList(userID string) (roleList []string, err error) {
|
||||||
|
roleList, err = c.enforcer.GetRolesForUser(userID)
|
||||||
|
return roleList, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CasbinAuthz) GetRoleUserList(roleName string) (userIDList []string, err error) {
|
||||||
|
userIDList, err = c.enforcer.GetUsersForRole(roleName)
|
||||||
|
return userIDList, err
|
||||||
|
}
|
||||||
14
business/authz/casbinauth/rbac_model.conf
Normal file
14
business/authz/casbinauth/rbac_model.conf
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[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
|
||||||
94
business/jxstore/cms/authz.go
Normal file
94
business/jxstore/cms/authz.go
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
package cms
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.rosy.net.cn/jx-callback/business/auth2"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/model"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/model/legacymodel"
|
||||||
|
"git.rosy.net.cn/jx-callback/globals/api2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TransferLegacyWeixins() (err error) {
|
||||||
|
// DELETE t1
|
||||||
|
// FROM auth_bind t1
|
||||||
|
// WHERE t1.created_at > '2019-08-05';
|
||||||
|
|
||||||
|
// DELETE t1
|
||||||
|
// FROM user t1
|
||||||
|
// WHERE t1.created_at > '2019-08-05';
|
||||||
|
|
||||||
|
// DELETE t1
|
||||||
|
// FROM casbin_rule t1;
|
||||||
|
|
||||||
|
sql := `
|
||||||
|
SELECT *
|
||||||
|
FROM weixins
|
||||||
|
ORDER BY parentid`
|
||||||
|
var weixinList []*legacymodel.WeiXins
|
||||||
|
db := dao.GetDB()
|
||||||
|
err = dao.GetRows(db, &weixinList, sql)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
parentMap := make(map[int]*legacymodel.WeiXins)
|
||||||
|
for _, v := range weixinList {
|
||||||
|
if v.ParentID == -1 {
|
||||||
|
parentMap[v.ID] = v
|
||||||
|
} else {
|
||||||
|
if parentMap[v.ParentID] != nil {
|
||||||
|
v.JxStoreID = parentMap[v.ParentID].JxStoreID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v.Tel != "" {
|
||||||
|
user := &model.User{
|
||||||
|
UserID2: v.Tel,
|
||||||
|
Name: v.NickName,
|
||||||
|
Mobile: v.Tel,
|
||||||
|
Type: model.UserTypeStoreBoss,
|
||||||
|
}
|
||||||
|
if user.Name == "" {
|
||||||
|
user.Name = user.Mobile
|
||||||
|
}
|
||||||
|
userList, err2 := dao.GetUsers(db, 0, "", "", v.Tel, "")
|
||||||
|
if err = err2; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// globals.SugarLogger.Debug(utils.Format4Output(user, false))
|
||||||
|
if len(userList) == 0 {
|
||||||
|
err = CreateUser(user)
|
||||||
|
} else {
|
||||||
|
user = userList[0]
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if v.OpenID != "" {
|
||||||
|
auth2.AddAuthBind(user, &auth2.AuthInfo{
|
||||||
|
AuthBindInfo: &auth2.AuthBindEx{
|
||||||
|
AuthBind: model.AuthBind{
|
||||||
|
Type: weixin.AuthTypeMP,
|
||||||
|
AuthID: v.OpenID,
|
||||||
|
AuthID2: v.OpenIDUnion,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if v.OpenIDMini != "" {
|
||||||
|
auth2.AddAuthBind(user, &auth2.AuthInfo{
|
||||||
|
AuthBindInfo: &auth2.AuthBindEx{
|
||||||
|
AuthBind: model.AuthBind{
|
||||||
|
Type: weixin.AuthTypeMini,
|
||||||
|
AuthID: v.OpenIDMini,
|
||||||
|
AuthID2: v.OpenIDUnion,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if v.JxStoreID > 0 {
|
||||||
|
api2.RoleMan.AddStoreRole4User(user.GetID(), v.JxStoreID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
29
business/jxstore/cms/authz_test.go
Normal file
29
business/jxstore/cms/authz_test.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package cms
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
|
"git.rosy.net.cn/jx-callback/globals/api2"
|
||||||
|
|
||||||
|
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai"
|
||||||
|
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/elm"
|
||||||
|
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/jd"
|
||||||
|
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/mtwm"
|
||||||
|
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/weimob/wsc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTransferLegacyWeixins(t *testing.T) {
|
||||||
|
err := TransferLegacyWeixins()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCasbin(t *testing.T) {
|
||||||
|
userList, err := api2.RoleMan.GetRoleUserList("role/store/100324")
|
||||||
|
t.Log(utils.Format4Output(userList, false))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
14
globals/api2/api2.go
Normal file
14
globals/api2/api2.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package api2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.rosy.net.cn/jx-callback/business/authz"
|
||||||
|
"git.rosy.net.cn/jx-callback/business/authz/casbinauth"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
RoleMan authz.IAuthz
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init() {
|
||||||
|
RoleMan, _ = casbinauth.New("business/authz/casbinauth/rbac_model.conf")
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package beegodb
|
package beegodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"git.rosy.net.cn/jx-callback/business/authz/casbinauth"
|
||||||
"git.rosy.net.cn/jx-callback/business/model"
|
"git.rosy.net.cn/jx-callback/business/model"
|
||||||
"git.rosy.net.cn/jx-callback/business/model/legacymodel"
|
"git.rosy.net.cn/jx-callback/business/model/legacymodel"
|
||||||
"git.rosy.net.cn/jx-callback/globals"
|
"git.rosy.net.cn/jx-callback/globals"
|
||||||
@@ -51,6 +52,8 @@ func Init() {
|
|||||||
orm.RegisterModel(&model.Act{}, &model.ActOrderRule{}, &model.ActStoreSku{})
|
orm.RegisterModel(&model.Act{}, &model.ActOrderRule{}, &model.ActStoreSku{})
|
||||||
orm.RegisterModel(&model.ActMap{}, &model.ActStoreSkuMap{})
|
orm.RegisterModel(&model.ActMap{}, &model.ActStoreSkuMap{})
|
||||||
orm.RegisterModel(&model.NewConfig{})
|
orm.RegisterModel(&model.NewConfig{})
|
||||||
|
|
||||||
|
casbinauth.RegisterModel()
|
||||||
// create table
|
// create table
|
||||||
orm.RunSyncdb("default", false, true)
|
orm.RunSyncdb("default", false, true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ package testinit
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.rosy.net.cn/jx-callback/globals/api"
|
"git.rosy.net.cn/jx-callback/globals/api"
|
||||||
|
"git.rosy.net.cn/jx-callback/globals/api2"
|
||||||
"git.rosy.net.cn/jx-callback/globals/testinit1"
|
"git.rosy.net.cn/jx-callback/globals/testinit1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Init() {
|
func Init() {
|
||||||
testinit1.Init()
|
testinit1.Init()
|
||||||
api.Init()
|
api.Init()
|
||||||
|
api2.Init()
|
||||||
}
|
}
|
||||||
|
|||||||
3
main.go
3
main.go
@@ -17,6 +17,7 @@ import (
|
|||||||
"git.rosy.net.cn/jx-callback/business/partner/purchase/ebai"
|
"git.rosy.net.cn/jx-callback/business/partner/purchase/ebai"
|
||||||
"git.rosy.net.cn/jx-callback/globals"
|
"git.rosy.net.cn/jx-callback/globals"
|
||||||
"git.rosy.net.cn/jx-callback/globals/api"
|
"git.rosy.net.cn/jx-callback/globals/api"
|
||||||
|
"git.rosy.net.cn/jx-callback/globals/api2"
|
||||||
"git.rosy.net.cn/jx-callback/globals/beegodb"
|
"git.rosy.net.cn/jx-callback/globals/beegodb"
|
||||||
_ "git.rosy.net.cn/jx-callback/routers"
|
_ "git.rosy.net.cn/jx-callback/routers"
|
||||||
|
|
||||||
@@ -46,6 +47,8 @@ var (
|
|||||||
|
|
||||||
func Init() {
|
func Init() {
|
||||||
beegodb.Init()
|
beegodb.Init()
|
||||||
|
api2.Init()
|
||||||
|
|
||||||
defsch.Init()
|
defsch.Init()
|
||||||
buildTime, err := time.ParseInLocation(time.RFC3339, BuildDate, time.UTC)
|
buildTime, err := time.ParseInLocation(time.RFC3339, BuildDate, time.UTC)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user