gofiber-study/middleware/casbin.go

121 lines
3.5 KiB
Go
Raw Normal View History

package middleware
import (
"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
"github.com/casbin/xorm-adapter/v2"
_ "github.com/go-sql-driver/mysql"
2022-10-22 18:18:45 +08:00
"github.com/gofiber/fiber/v2"
"gofiber.study.skcks.cn/common/errorx"
"gofiber.study.skcks.cn/common/logger"
"gofiber.study.skcks.cn/common/utils"
"gofiber.study.skcks.cn/global"
"gofiber.study.skcks.cn/model/casbin_model/models"
models2 "gofiber.study.skcks.cn/model/generic/models"
"xorm.io/xorm"
)
2022-10-22 18:18:45 +08:00
const (
DefaultSystem = "WEB"
CasBinSeparator = "::"
)
2022-11-26 20:22:38 +08:00
func NewCasbin(app *fiber.App, engine *xorm.EngineGroup) {
casbinModels := make([]models.CasbinModel, 0)
err := engine.Find(&casbinModels)
if err != nil {
logger.Log.Fatalf("[x] [casbin] model 加载失败: %s", err)
}
m := model.NewModel()
for _, casbinModel := range casbinModels {
m.AddDef(casbinModel.Type, casbinModel.Name, casbinModel.Rule)
}
// CasBin Xorm 适配器
// 若 不指定库名 且 不存在数据库 则会自动创建 casbin 数据库 和 casbin_rule 表
// 若 指定库名 三个参数 为 true 且 必须保证数据库已经存在 如果 不存在 casbin_rule 表 则会自动创建
//a, _ := xormadapter.NewAdapter("mysql", "root:12341234@tcp(10.10.10.100:3306)/")
a, _ := xormadapter.NewAdapter("mysql", engine.DataSourceName(), true)
e, _ := casbin.NewEnforcer(m, a)
// 启用自动保存选项。
e.EnableAutoSave(true)
err = e.LoadPolicy()
if err != nil {
logger.Log.Fatalf("[x] [casbin] policy 加载失败: %s", err)
}
// 初始化 role::root 组权限
2022-11-26 20:22:38 +08:00
initRootGroupPermission(app, e)
global.Enforcer = e
utils.MainAppExec(func() {
logger.Log.Infof("[√] [casbin] 加载成功")
})
}
2022-11-26 20:22:38 +08:00
func initRootGroupPermission(app *fiber.App, e *casbin.Enforcer) {
// 添加/修改 组策略
// role::root 组 继承 root 的权限
_, _ = e.AddGroupingPolicy("role::root", "user::root")
2022-11-26 20:22:38 +08:00
for _, routes := range app.Stack() {
for _, route := range routes {
_, _ = e.AddPolicy("role::root", DefaultSystem, route.Path, route.Method)
}
}
}
2022-10-22 18:18:45 +08:00
func CasbinMiddleWare(c *fiber.Ctx) error {
headers := c.GetReqHeaders()
logger.Log.Debugf("headers %v", headers)
token := headers["Token"]
logger.Log.Debugf("token %s", token)
userClaim, err := global.ParseToken(token)
if err != nil {
logger.Log.Errorf("[CasbinMiddleWare] 认证错误 %s", err)
return c.JSON(errorx.NewErrorWithCode(fiber.StatusUnauthorized, "认证失效, 请重新登录"))
}
user := &models2.User{
Id: userClaim.Id,
Account: userClaim.Account,
}
exist, err := global.DataSources.Get(user)
if !exist {
logger.Log.Errorf("[CasbinMiddleWare] 用户不存在 %s", err)
return c.JSON(errorx.NewErrorWithCode(fiber.StatusUnauthorized, "认证失效, 请重新登录"))
}
if !user.Active {
logger.Log.Errorf("[CasbinMiddleWare] 账号未启用 id: %s, account: %s", user.Id, user.Account)
return c.JSON(errorx.NewErrorWithCode(fiber.StatusUnauthorized, "该账号暂未启用"))
}
2022-10-22 18:18:45 +08:00
identify := userClaim.Identify
system := headers["System"]
if len(system) == 0 {
system = DefaultSystem
}
uri := string(c.Request().URI().Path())
method := c.Method()
logger.Log.Debugf("[CasbinMiddleWare] identify=>%s, system=>%s, uri=>%s, method=>%s", identify, system, uri, method)
2022-10-22 18:18:45 +08:00
hasPermission, err := global.Enforcer.Enforce(identify, system, uri, method)
if err != nil {
return c.JSON(errorx.ParseError(err))
}
if hasPermission {
return c.Next()
} else {
return c.JSON(errorx.NewErrorWithCode(fiber.StatusForbidden, "无权访问"))
}
}