2022-08-07 23:55:03 +08:00
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package object
import (
2023-01-15 12:06:10 +08:00
"fmt"
2022-08-07 23:55:03 +08:00
"strings"
"github.com/casbin/casbin/v2"
2023-01-15 12:06:10 +08:00
"github.com/casbin/casbin/v2/config"
2023-03-19 19:13:48 +07:00
"github.com/casbin/casbin/v2/log"
2022-08-07 23:55:03 +08:00
"github.com/casbin/casbin/v2/model"
"github.com/casdoor/casdoor/conf"
2023-12-02 15:26:52 +08:00
"github.com/casdoor/casdoor/util"
2023-02-12 09:33:24 +08:00
xormadapter "github.com/casdoor/xorm-adapter/v3"
2022-08-07 23:55:03 +08:00
)
2023-10-22 02:30:29 +08:00
func getPermissionEnforcer ( p * Permission , permissionIDs ... string ) ( * casbin . Enforcer , error ) {
2023-03-19 19:13:48 +07:00
// Init an enforcer instance without specifying a model or adapter.
// If you specify an adapter, it will load all policies, which is a
// heavy process that can slow down the application.
enforcer , err := casbin . NewEnforcer ( & log . DefaultLogger { } , false )
if err != nil {
2023-10-22 02:30:29 +08:00
return nil , err
2023-03-19 19:13:48 +07:00
}
2023-01-17 09:27:02 +07:00
2023-07-24 14:02:34 +08:00
err = p . setEnforcerModel ( enforcer )
2023-05-12 21:32:48 +08:00
if err != nil {
2023-10-22 02:30:29 +08:00
return nil , err
2023-05-12 21:32:48 +08:00
}
2023-07-24 14:02:34 +08:00
err = p . setEnforcerAdapter ( enforcer )
if err != nil {
2023-10-22 02:30:29 +08:00
return nil , err
2023-07-24 14:02:34 +08:00
}
2023-03-19 19:13:48 +07:00
2023-07-24 14:02:34 +08:00
policyFilterV5 := [ ] string { p . GetId ( ) }
2023-06-22 13:40:09 +07:00
if len ( permissionIDs ) != 0 {
policyFilterV5 = permissionIDs
}
2023-03-19 19:13:48 +07:00
policyFilter := xormadapter . Filter {
2023-06-22 13:40:09 +07:00
V5 : policyFilterV5 ,
2023-01-17 09:27:02 +07:00
}
2023-07-24 14:02:34 +08:00
if ! HasRoleDefinition ( enforcer . GetModel ( ) ) {
2023-03-19 19:13:48 +07:00
policyFilter . Ptype = [ ] string { "p" }
2022-08-07 23:55:03 +08:00
}
2023-01-17 09:27:02 +07:00
err = enforcer . LoadFilteredPolicy ( policyFilter )
2023-01-15 12:06:10 +08:00
if err != nil {
2023-10-22 02:30:29 +08:00
return nil , err
2023-01-15 12:06:10 +08:00
}
2023-03-19 19:13:48 +07:00
2023-10-22 02:30:29 +08:00
return enforcer , nil
2022-08-07 23:55:03 +08:00
}
2023-07-24 14:02:34 +08:00
func ( p * Permission ) setEnforcerAdapter ( enforcer * casbin . Enforcer ) error {
tableName := "permission_rule"
if len ( p . Adapter ) != 0 {
2023-07-29 15:07:04 +08:00
adapterObj , err := getAdapter ( p . Owner , p . Adapter )
2023-07-24 14:02:34 +08:00
if err != nil {
return err
}
if adapterObj != nil && adapterObj . Table != "" {
tableName = adapterObj . Table
}
}
tableNamePrefix := conf . GetConfigString ( "tableNamePrefix" )
2023-09-01 18:00:17 +08:00
adapter , err := xormadapter . NewAdapterByEngineWithTableName ( ormer . Engine , tableName , tableNamePrefix )
2023-07-24 14:02:34 +08:00
if err != nil {
return err
}
2023-07-29 15:07:04 +08:00
enforcer . SetAdapter ( adapter )
2023-07-24 14:02:34 +08:00
return nil
}
func ( p * Permission ) setEnforcerModel ( enforcer * casbin . Enforcer ) error {
permissionModel , err := getModel ( p . Owner , p . Model )
if err != nil {
return err
}
// TODO: return error if permissionModel is nil.
m := model . Model { }
if permissionModel != nil {
m , err = GetBuiltInModel ( permissionModel . ModelText )
} else {
m , err = GetBuiltInModel ( "" )
}
if err != nil {
return err
}
err = enforcer . InitWithModelAndAdapter ( m , nil )
if err != nil {
return err
}
return nil
}
2023-01-17 09:27:02 +07:00
func getPolicies ( permission * Permission ) [ ] [ ] string {
2022-08-07 23:55:03 +08:00
var policies [ ] [ ] string
2023-01-17 09:27:02 +07:00
2023-01-15 12:06:10 +08:00
permissionId := permission . GetId ( )
2022-08-18 11:49:32 +08:00
domainExist := len ( permission . Domains ) > 0
2023-01-17 09:27:02 +07:00
2023-07-21 18:01:37 +08:00
usersAndRoles := append ( permission . Users , permission . Roles ... )
for _ , userOrRole := range usersAndRoles {
2022-08-07 23:55:03 +08:00
for _ , resource := range permission . Resources {
for _ , action := range permission . Actions {
2022-08-18 11:49:32 +08:00
if domainExist {
for _ , domain := range permission . Domains {
2025-08-02 13:38:49 +08:00
policies = append ( policies , [ ] string { userOrRole , domain , resource , action , strings . ToLower ( permission . Effect ) , permissionId } )
2022-08-18 11:49:32 +08:00
}
} else {
2025-08-02 13:38:49 +08:00
policies = append ( policies , [ ] string { userOrRole , resource , action , strings . ToLower ( permission . Effect ) , "" , permissionId } )
2023-01-17 09:27:02 +07:00
}
}
}
}
return policies
}
2023-05-30 15:49:39 +08:00
func getRolesInRole ( roleId string , visited map [ string ] struct { } ) ( [ ] * Role , error ) {
2023-12-02 15:26:52 +08:00
roleOwner , roleName := util . GetOwnerAndNameFromId ( roleId )
if roleName == "*" {
roles , err := GetRoles ( roleOwner )
if err != nil {
return [ ] * Role { } , err
}
return roles , nil
}
2023-05-30 15:49:39 +08:00
role , err := GetRole ( roleId )
if err != nil {
return [ ] * Role { } , err
}
2023-04-28 21:14:37 +07:00
if role == nil {
2023-05-30 15:49:39 +08:00
return [ ] * Role { } , nil
2023-04-28 21:14:37 +07:00
}
visited [ roleId ] = struct { } { }
roles := [ ] * Role { role }
for _ , subRole := range role . Roles {
if _ , ok := visited [ subRole ] ; ! ok {
2023-05-30 15:49:39 +08:00
r , err := getRolesInRole ( subRole , visited )
if err != nil {
return [ ] * Role { } , err
}
roles = append ( roles , r ... )
2023-04-28 21:14:37 +07:00
}
}
2023-05-30 15:49:39 +08:00
return roles , nil
2023-04-28 21:14:37 +07:00
}
2023-12-02 15:26:52 +08:00
func getGroupingPolicies ( permission * Permission ) ( [ ] [ ] string , error ) {
2023-01-17 09:27:02 +07:00
var groupingPolicies [ ] [ ] string
domainExist := len ( permission . Domains ) > 0
permissionId := permission . GetId ( )
2023-04-28 21:14:37 +07:00
for _ , roleId := range permission . Roles {
visited := map [ string ] struct { } { }
2023-12-02 15:26:52 +08:00
if roleId == "*" {
roleId = util . GetId ( permission . Owner , "*" )
}
2023-05-30 15:49:39 +08:00
rolesInRole , err := getRolesInRole ( roleId , visited )
if err != nil {
2023-12-02 15:26:52 +08:00
return nil , err
2023-05-30 15:49:39 +08:00
}
2023-12-02 15:26:52 +08:00
2023-04-28 21:14:37 +07:00
for _ , role := range rolesInRole {
2023-12-02 15:26:52 +08:00
roleId = role . GetId ( )
2023-04-28 21:14:37 +07:00
for _ , subUser := range role . Users {
if domainExist {
for _ , domain := range permission . Domains {
groupingPolicies = append ( groupingPolicies , [ ] string { subUser , roleId , domain , "" , "" , permissionId } )
}
} else {
groupingPolicies = append ( groupingPolicies , [ ] string { subUser , roleId , "" , "" , "" , permissionId } )
2022-08-18 11:49:32 +08:00
}
}
2023-01-17 09:27:02 +07:00
2023-04-28 21:14:37 +07:00
for _ , subRole := range role . Roles {
if domainExist {
for _ , domain := range permission . Domains {
groupingPolicies = append ( groupingPolicies , [ ] string { subRole , roleId , domain , "" , "" , permissionId } )
}
} else {
groupingPolicies = append ( groupingPolicies , [ ] string { subRole , roleId , "" , "" , "" , permissionId } )
2022-08-18 11:49:32 +08:00
}
}
}
2022-08-07 23:55:03 +08:00
}
2023-01-17 09:27:02 +07:00
2023-12-02 15:26:52 +08:00
return groupingPolicies , nil
2022-08-07 23:55:03 +08:00
}
2023-10-22 02:30:29 +08:00
func addPolicies ( permission * Permission ) error {
enforcer , err := getPermissionEnforcer ( permission )
if err != nil {
return err
}
2023-01-17 09:27:02 +07:00
policies := getPolicies ( permission )
2023-10-22 02:30:29 +08:00
_ , err = enforcer . AddPolicies ( policies )
return err
}
func removePolicies ( permission * Permission ) error {
enforcer , err := getPermissionEnforcer ( permission )
2023-01-17 09:27:02 +07:00
if err != nil {
2023-10-22 02:30:29 +08:00
return err
2023-01-17 09:27:02 +07:00
}
2023-10-22 02:30:29 +08:00
policies := getPolicies ( permission )
_ , err = enforcer . RemovePolicies ( policies )
return err
2023-01-17 09:27:02 +07:00
}
2023-10-22 02:30:29 +08:00
func addGroupingPolicies ( permission * Permission ) error {
enforcer , err := getPermissionEnforcer ( permission )
if err != nil {
return err
}
2023-12-02 15:26:52 +08:00
groupingPolicies , err := getGroupingPolicies ( permission )
if err != nil {
return err
}
2022-08-18 11:49:32 +08:00
if len ( groupingPolicies ) > 0 {
2023-10-22 02:30:29 +08:00
_ , err = enforcer . AddGroupingPolicies ( groupingPolicies )
2022-08-18 11:49:32 +08:00
if err != nil {
2023-10-22 02:30:29 +08:00
return err
2022-08-18 11:49:32 +08:00
}
}
2023-10-22 02:30:29 +08:00
return nil
2022-08-07 23:55:03 +08:00
}
2023-10-22 02:30:29 +08:00
func removeGroupingPolicies ( permission * Permission ) error {
enforcer , err := getPermissionEnforcer ( permission )
if err != nil {
return err
}
2023-12-02 15:26:52 +08:00
groupingPolicies , err := getGroupingPolicies ( permission )
if err != nil {
return err
}
2022-08-07 23:55:03 +08:00
2022-08-18 11:49:32 +08:00
if len ( groupingPolicies ) > 0 {
2023-10-22 02:30:29 +08:00
_ , err = enforcer . RemoveGroupingPolicies ( groupingPolicies )
2022-08-18 11:49:32 +08:00
if err != nil {
2023-10-22 02:30:29 +08:00
return err
2022-08-18 11:49:32 +08:00
}
2022-08-15 10:24:26 +08:00
}
2023-10-22 02:30:29 +08:00
return nil
2022-08-15 10:24:26 +08:00
}
2023-12-29 15:12:40 +08:00
func Enforce ( permission * Permission , request [ ] string , permissionIds ... string ) ( bool , error ) {
2023-10-22 02:30:29 +08:00
enforcer , err := getPermissionEnforcer ( permission , permissionIds ... )
if err != nil {
return false , err
}
2023-12-29 15:12:40 +08:00
// type transformation
interfaceRequest := util . StringToInterfaceArray ( request )
return enforcer . Enforce ( interfaceRequest ... )
2022-08-07 23:55:03 +08:00
}
2023-12-29 15:12:40 +08:00
func BatchEnforce ( permission * Permission , requests [ ] [ ] string , permissionIds ... string ) ( [ ] bool , error ) {
2023-10-22 02:30:29 +08:00
enforcer , err := getPermissionEnforcer ( permission , permissionIds ... )
if err != nil {
return nil , err
}
2023-12-29 15:12:40 +08:00
// type transformation
interfaceRequests := util . StringToInterfaceArray2d ( requests )
return enforcer . BatchEnforce ( interfaceRequests )
2022-08-07 23:55:03 +08:00
}
2024-01-13 09:58:55 +08:00
func getEnforcers ( userId string ) ( [ ] * casbin . Enforcer , error ) {
2023-09-24 08:01:18 +08:00
permissions , _ , err := getPermissionsAndRolesByUser ( userId )
2023-05-30 15:49:39 +08:00
if err != nil {
2023-10-22 02:30:29 +08:00
return nil , err
2023-05-30 15:49:39 +08:00
}
2023-12-02 15:26:52 +08:00
allRoles , err := GetAllRoles ( userId )
if err != nil {
return nil , err
}
for _ , role := range allRoles {
2024-01-13 09:58:55 +08:00
var permissionsByRole [ ] * Permission
permissionsByRole , err = GetPermissionsByRole ( role )
2023-05-30 15:49:39 +08:00
if err != nil {
2023-10-22 02:30:29 +08:00
return nil , err
2023-05-30 15:49:39 +08:00
}
permissions = append ( permissions , permissionsByRole ... )
2022-08-18 11:49:32 +08:00
}
2024-01-13 09:58:55 +08:00
var enforcers [ ] * casbin . Enforcer
2022-08-07 23:55:03 +08:00
for _ , permission := range permissions {
2024-01-13 09:58:55 +08:00
var enforcer * casbin . Enforcer
enforcer , err = getPermissionEnforcer ( permission )
2023-10-22 02:30:29 +08:00
if err != nil {
return nil , err
}
2024-01-13 09:58:55 +08:00
enforcers = append ( enforcers , enforcer )
2022-08-07 23:55:03 +08:00
}
2024-01-13 09:58:55 +08:00
return enforcers , nil
2022-08-07 23:55:03 +08:00
}
2023-10-22 02:30:29 +08:00
func GetAllObjects ( userId string ) ( [ ] string , error ) {
2024-01-13 09:58:55 +08:00
enforcers , err := getEnforcers ( userId )
if err != nil {
return nil , err
}
res := [ ] string { }
for _ , enforcer := range enforcers {
items := enforcer . GetAllObjects ( )
res = append ( res , items ... )
}
return res , nil
2022-08-07 23:55:03 +08:00
}
2023-10-22 02:30:29 +08:00
func GetAllActions ( userId string ) ( [ ] string , error ) {
2024-01-13 09:58:55 +08:00
enforcers , err := getEnforcers ( userId )
if err != nil {
return nil , err
}
res := [ ] string { }
for _ , enforcer := range enforcers {
2024-10-16 21:55:06 +08:00
items := enforcer . GetAllActions ( )
2024-01-13 09:58:55 +08:00
res = append ( res , items ... )
}
return res , nil
2022-08-07 23:55:03 +08:00
}
2023-12-02 15:26:52 +08:00
func GetAllRoles ( userId string ) ( [ ] string , error ) {
2023-09-24 08:01:18 +08:00
roles , err := getRolesByUser ( userId )
2023-05-30 15:49:39 +08:00
if err != nil {
2023-12-02 15:26:52 +08:00
return nil , err
2023-05-30 15:49:39 +08:00
}
2023-12-02 15:26:52 +08:00
res := [ ] string { }
2022-08-07 23:55:03 +08:00
for _ , role := range roles {
res = append ( res , role . Name )
}
2023-12-02 15:26:52 +08:00
return res , nil
2022-08-07 23:55:03 +08:00
}
2023-01-15 12:06:10 +08:00
func GetBuiltInModel ( modelText string ) ( model . Model , error ) {
if modelText == "" {
2023-08-14 12:09:38 +08:00
modelText = ` [ request_definition ]
2023-01-15 12:06:10 +08:00
r = sub , obj , act
[ policy_definition ]
p = sub , obj , act , "" , "" , permissionId
[ 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 `
return model . NewModelFromString ( modelText )
} else {
cfg , err := config . NewConfigFromText ( modelText )
if err != nil {
return nil , err
}
// load [policy_definition]
policyDefinition := strings . Split ( cfg . String ( "policy_definition::p" ) , "," )
2023-10-22 02:30:29 +08:00
2023-01-15 12:06:10 +08:00
fieldsNum := len ( policyDefinition )
2025-08-29 22:39:39 +08:00
if fieldsNum > builtInMaxFields {
return nil , fmt . Errorf ( "the maximum policy_definition field number cannot exceed %d, got %d" , builtInMaxFields , fieldsNum )
2023-01-15 12:06:10 +08:00
}
2023-10-22 02:30:29 +08:00
2023-01-15 12:06:10 +08:00
// filled empty field with "" and V5 with "permissionId"
2025-08-29 22:39:39 +08:00
if fieldsNum == builtInMaxFields {
sixthField := strings . TrimSpace ( policyDefinition [ builtInMaxFields - 1 ] )
if sixthField != "permissionId" {
return nil , fmt . Errorf ( "when adding policies with permissions, the sixth field of policy_definition must be permissionId, got %s" , policyDefinition [ builtInMaxFields - 1 ] )
}
} else {
needFill := builtInMaxFields - fieldsNum
for i := 0 ; i < needFill - 1 ; i ++ {
policyDefinition = append ( policyDefinition , "" )
}
policyDefinition = append ( policyDefinition , "permissionId" )
2023-01-15 12:06:10 +08:00
}
2023-10-22 02:30:29 +08:00
m , err := model . NewModelFromString ( modelText )
if err != nil {
return nil , err
}
2023-01-15 12:06:10 +08:00
m . AddDef ( "p" , "p" , strings . Join ( policyDefinition , "," ) )
return m , err
}
}