feat: implement access control using casbin (#806)

* feat: implement access control using casbin

Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com>

* chore: sort imports

Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com>

* fix: remove

Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com>

* Update auth.go

Co-authored-by: Gucheng <85475922+nomeguy@users.noreply.github.com>
This commit is contained in:
Yixiang Zhao
2022-07-13 00:34:35 +08:00
committed by GitHub
parent de49a45e19
commit 2bca424370
5 changed files with 159 additions and 1 deletions

View File

@ -203,6 +203,11 @@ func (a *Adapter) createTable() {
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(PermissionRule))
if err != nil {
panic(err)
}
}
func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {

View File

@ -229,4 +229,21 @@ func CheckUserPermission(requestUserId, userId string, strict bool) (bool, error
}
return hasPermission, fmt.Errorf("you don't have the permission to do this")
}
func CheckPermission(userId string, application *Application) (bool, error) {
permissions := GetPermissions(application.Organization)
allow := true
var err error
for _, permission := range permissions {
if permission.IsEnabled {
for _, resource := range permission.Resources {
if resource == application.Name {
enforcer := getEnforcer(permission)
allow, err = enforcer.Enforce(userId, application.Name, "read")
}
}
}
}
return allow, err
}

View File

@ -16,7 +16,12 @@ package object
import (
"fmt"
"strings"
"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
xormadapter "github.com/casbin/xorm-adapter/v2"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/util"
"xorm.io/core"
)
@ -39,6 +44,16 @@ type Permission struct {
IsEnabled bool `json:"isEnabled"`
}
type PermissionRule struct {
PType string `xorm:"varchar(100) index not null default ''"`
V0 string `xorm:"varchar(100) index not null default ''"`
V1 string `xorm:"varchar(100) index not null default ''"`
V2 string `xorm:"varchar(100) index not null default ''"`
V3 string `xorm:"varchar(100) index not null default ''"`
V4 string `xorm:"varchar(100) index not null default ''"`
V5 string `xorm:"varchar(100) index not null default ''"`
}
func GetPermissionCount(owner, field, value string) int {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Permission{})
@ -95,7 +110,8 @@ func GetPermission(id string) *Permission {
func UpdatePermission(id string, permission *Permission) bool {
owner, name := util.GetOwnerAndNameFromId(id)
if getPermission(owner, name) == nil {
oldPermission := getPermission(owner, name)
if oldPermission == nil {
return false
}
@ -104,6 +120,11 @@ func UpdatePermission(id string, permission *Permission) bool {
panic(err)
}
if affected != 0 {
removePolicies(oldPermission)
addPolicies(permission)
}
return affected != 0
}
@ -113,6 +134,10 @@ func AddPermission(permission *Permission) bool {
panic(err)
}
if affected != 0 {
addPolicies(permission)
}
return affected != 0
}
@ -122,9 +147,85 @@ func DeletePermission(permission *Permission) bool {
panic(err)
}
if affected != 0 {
removePolicies(permission)
}
return affected != 0
}
func (permission *Permission) GetId() string {
return fmt.Sprintf("%s/%s", permission.Owner, permission.Name)
}
func getEnforcer(permission *Permission) *casbin.Enforcer {
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
adapter, err := xormadapter.NewAdapterWithTableName(conf.GetConfigString("driverName"), conf.GetBeegoConfDataSourceName()+conf.GetConfigString("dbName"), "permission_rule", tableNamePrefix, true)
if err != nil {
panic(err)
}
modelText := `
[request_definition]
r = sub, obj, act
[policy_definition]
p = permission, sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act`
permissionModel := getModel(permission.Owner, permission.Model)
if permissionModel != nil {
modelText = permissionModel.ModelText
}
m, err := model.NewModelFromString(modelText)
if err != nil {
panic(err)
}
enforcer, err := casbin.NewEnforcer(m, adapter)
if err != nil {
panic(err)
}
err = enforcer.LoadFilteredPolicy(xormadapter.Filter{V0: []string{permission.GetId()}})
if err != nil {
panic(err)
}
return enforcer
}
func getPolicies(permission *Permission) [][]string {
var policies [][]string
for _, user := range permission.Users {
for _, resource := range permission.Resources {
for _, action := range permission.Actions {
policies = append(policies, []string{permission.GetId(), user, resource, strings.ToLower(action)})
}
}
}
return policies
}
func addPolicies(permission *Permission) {
enforcer := getEnforcer(permission)
policies := getPolicies(permission)
_, err := enforcer.AddPolicies(policies)
if err != nil {
panic(err)
}
}
func removePolicies(permission *Permission) {
enforcer := getEnforcer(permission)
_, err := enforcer.RemoveFilteredPolicy(0, permission.GetId())
if err != nil {
panic(err)
}
}