123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- package rbac
- import (
- "fmt"
- "git.bvbej.com/bvbej/base-golang/pkg/rbac/model"
- "github.com/casbin/casbin/v2"
- casbinModel "github.com/casbin/casbin/v2/model"
- gormAdapter "github.com/casbin/gorm-adapter/v3"
- "github.com/gin-gonic/gin"
- "go.uber.org/zap"
- "gorm.io/gorm"
- "net/http"
- )
- var _ Auth = (*auth)(nil)
- type Auth interface {
- AddRole(role, describe string) error
- DeleteRole(role string) (bool, error)
- AddRoleForUser(user, role string) (bool, error)
- UpdateRoleForUser(user, role string) (bool, error)
- UpdateRolePermission(role string, permissionIDs []uint64) (bool, error)
- CreatePermission(info gin.RoutesInfo)
- UpdatePermission(id uint64, url, description string) error
- CheckPermission(user string, r *http.Request) bool
- }
- type auth struct {
- db *gorm.DB
- enforcer *casbin.Enforcer
- logger *zap.Logger
- }
- func NewRBAC(db *gorm.DB, logger *zap.Logger) (Auth, error) {
- rule := new(model.RbacRules)
- gormAdapter.TurnOffAutoMigrate(db)
- t, err := gormAdapter.NewAdapterByDBWithCustomTable(db, rule, rule.TableName())
- 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) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*") || r.sub == "admin"
- `)
- if err != nil {
- return nil, err
- }
- enforcer, err := casbin.NewEnforcer(m, t)
- if err != nil {
- return nil, err
- }
- return &auth{
- db: db,
- enforcer: enforcer,
- logger: logger,
- }, nil
- }
- func (a *auth) AddRole(role, describe string) error {
- if a.db.Where("name = ?", role).First(&model.RbacRoles{}).RowsAffected > 0 {
- return fmt.Errorf("角色已存在")
- }
- return a.db.Create(&model.RbacRoles{
- Name: role,
- Describe: describe,
- }).Error
- }
- func (a *auth) DeleteRole(role string) (bool, error) {
- err := a.db.Where("name = ?", role).Delete(&model.RbacRoles{}).Error
- if err != nil {
- return false, err
- }
- return a.enforcer.DeleteRole(role)
- }
- func (a *auth) AddRoleForUser(user, role string) (bool, error) {
- return a.enforcer.AddRoleForUser(user, role)
- }
- func (a *auth) UpdateRoleForUser(user, role string) (bool, error) {
- oldRole, err := a.enforcer.GetRolesForUser(user)
- if err != nil && len(oldRole) > 0 {
- return false, err
- }
- oldRule := []string{user, oldRole[0]}
- newRule := []string{user, role}
- return a.enforcer.UpdateGroupingPolicy(oldRule, newRule)
- }
- func (a *auth) UpdateRolePermission(role string, permissionIDs []uint64) (bool, error) {
- ok, err := a.enforcer.DeletePermissionsForUser(role)
- if err != nil {
- return ok, err
- }
- var rbacPermissions []model.RbacPermissions
- a.db.Where("id IN ?", permissionIDs).Find(&rbacPermissions)
- if len(rbacPermissions) > 0 {
- var permissions [][]string
- for _, permission := range rbacPermissions {
- permissions = append(permissions, []string{permission.Path, permission.Method})
- }
- return a.enforcer.AddPermissionsForUser(role, permissions...)
- }
- return false, fmt.Errorf("未找到需要添加的权限")
- }
- func (a *auth) CreatePermission(info gin.RoutesInfo) {
- for _, routeInfo := range info {
- a.db.Where("method = ? AND path = ?", routeInfo.Method, routeInfo.Path).
- FirstOrCreate(&model.RbacPermissions{
- Method: routeInfo.Method,
- Path: routeInfo.Path,
- })
- }
- }
- func (a *auth) UpdatePermission(id uint64, url, description string) error {
- return a.db.Where("id = ?", id).Updates(map[string]any{
- "url": url,
- "description": description,
- }).Error
- }
- func (a *auth) CheckPermission(user string, r *http.Request) bool {
- path := r.URL.Path
- method := r.Method
- allowed, err := a.enforcer.Enforce(user, path, method)
- if err != nil {
- a.logger.Sugar().Errorf("Enforce err [%s]", err)
- return false
- }
- return allowed
- }
|