| // Copyright 2017 The casbin 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 casbin |
| |
| import ( |
| "fmt" |
| "strings" |
| |
| "github.com/casbin/casbin/v3/rbac" |
| |
| "github.com/casbin/casbin/v3/constant" |
| "github.com/casbin/casbin/v3/errors" |
| "github.com/casbin/casbin/v3/util" |
| ) |
| |
| // GetRolesForUser gets the roles that a user has. |
| func (e *Enforcer) GetRolesForUser(name string, domain ...string) ([]string, error) { |
| rm := e.GetRoleManager() |
| if rm == nil { |
| return nil, fmt.Errorf("role manager is not initialized") |
| } |
| res, err := rm.GetRoles(name, domain...) |
| return res, err |
| } |
| |
| // GetUsersForRole gets the users that has a role. |
| func (e *Enforcer) GetUsersForRole(name string, domain ...string) ([]string, error) { |
| rm := e.GetRoleManager() |
| if rm == nil { |
| return nil, fmt.Errorf("role manager is not initialized") |
| } |
| res, err := rm.GetUsers(name, domain...) |
| return res, err |
| } |
| |
| // HasRoleForUser determines whether a user has a role. |
| func (e *Enforcer) HasRoleForUser(name string, role string, domain ...string) (bool, error) { |
| roles, err := e.GetRolesForUser(name, domain...) |
| if err != nil { |
| return false, err |
| } |
| hasRole := false |
| for _, r := range roles { |
| if r == role { |
| hasRole = true |
| break |
| } |
| } |
| |
| return hasRole, nil |
| } |
| |
| // AddRoleForUser adds a role for a user. |
| // Returns false if the user already has the role (aka not affected). |
| func (e *Enforcer) AddRoleForUser(user string, role string, domain ...string) (bool, error) { |
| args := []string{user, role} |
| args = append(args, domain...) |
| return e.AddGroupingPolicy(args) |
| } |
| |
| // AddRolesForUser adds roles for a user. |
| // Returns false if the user already has the roles (aka not affected). |
| func (e *Enforcer) AddRolesForUser(user string, roles []string, domain ...string) (bool, error) { |
| var rules [][]string |
| for _, role := range roles { |
| rule := []string{user, role} |
| rule = append(rule, domain...) |
| rules = append(rules, rule) |
| } |
| return e.AddGroupingPolicies(rules) |
| } |
| |
| // DeleteRoleForUser deletes a role for a user. |
| // Returns false if the user does not have the role (aka not affected). |
| func (e *Enforcer) DeleteRoleForUser(user string, role string, domain ...string) (bool, error) { |
| args := []string{user, role} |
| args = append(args, domain...) |
| return e.RemoveGroupingPolicy(args) |
| } |
| |
| // DeleteRolesForUser deletes all roles for a user. |
| // Returns false if the user does not have any roles (aka not affected). |
| func (e *Enforcer) DeleteRolesForUser(user string, domain ...string) (bool, error) { |
| var args []string |
| if len(domain) == 0 { |
| args = []string{user} |
| } else if len(domain) > 1 { |
| return false, errors.ErrDomainParameter |
| } else { |
| args = []string{user, "", domain[0]} |
| } |
| return e.RemoveFilteredGroupingPolicy(0, args...) |
| } |
| |
| // DeleteUser deletes a user. |
| // Returns false if the user does not exist (aka not affected). |
| func (e *Enforcer) DeleteUser(user string) (bool, error) { |
| var err error |
| res1, err := e.RemoveFilteredGroupingPolicy(0, user) |
| if err != nil { |
| return res1, err |
| } |
| |
| subIndex, err := e.GetFieldIndex("p", constant.SubjectIndex) |
| if err != nil { |
| return false, err |
| } |
| res2, err := e.RemoveFilteredPolicy(subIndex, user) |
| return res1 || res2, err |
| } |
| |
| // DeleteRole deletes a role. |
| // Returns false if the role does not exist (aka not affected). |
| func (e *Enforcer) DeleteRole(role string) (bool, error) { |
| var err error |
| res1, err := e.RemoveFilteredGroupingPolicy(0, role) |
| if err != nil { |
| return res1, err |
| } |
| |
| res2, err := e.RemoveFilteredGroupingPolicy(1, role) |
| if err != nil { |
| return res1, err |
| } |
| |
| subIndex, err := e.GetFieldIndex("p", constant.SubjectIndex) |
| if err != nil { |
| return false, err |
| } |
| res3, err := e.RemoveFilteredPolicy(subIndex, role) |
| return res1 || res2 || res3, err |
| } |
| |
| // DeletePermission deletes a permission. |
| // Returns false if the permission does not exist (aka not affected). |
| func (e *Enforcer) DeletePermission(permission ...string) (bool, error) { |
| return e.RemoveFilteredPolicy(1, permission...) |
| } |
| |
| // AddPermissionForUser adds a permission for a user or role. |
| // Returns false if the user or role already has the permission (aka not affected). |
| func (e *Enforcer) AddPermissionForUser(user string, permission ...string) (bool, error) { |
| return e.AddPolicy(util.JoinSlice(user, permission...)) |
| } |
| |
| // AddPermissionsForUser adds multiple permissions for a user or role. |
| // Returns false if the user or role already has one of the permissions (aka not affected). |
| func (e *Enforcer) AddPermissionsForUser(user string, permissions ...[]string) (bool, error) { |
| var rules [][]string |
| for _, permission := range permissions { |
| rules = append(rules, util.JoinSlice(user, permission...)) |
| } |
| return e.AddPolicies(rules) |
| } |
| |
| // DeletePermissionForUser deletes a permission for a user or role. |
| // Returns false if the user or role does not have the permission (aka not affected). |
| func (e *Enforcer) DeletePermissionForUser(user string, permission ...string) (bool, error) { |
| return e.RemovePolicy(util.JoinSlice(user, permission...)) |
| } |
| |
| // DeletePermissionsForUser deletes permissions for a user or role. |
| // Returns false if the user or role does not have any permissions (aka not affected). |
| func (e *Enforcer) DeletePermissionsForUser(user string) (bool, error) { |
| subIndex, err := e.GetFieldIndex("p", constant.SubjectIndex) |
| if err != nil { |
| return false, err |
| } |
| return e.RemoveFilteredPolicy(subIndex, user) |
| } |
| |
| // GetPermissionsForUser gets permissions for a user or role. |
| func (e *Enforcer) GetPermissionsForUser(user string, domain ...string) ([][]string, error) { |
| return e.GetNamedPermissionsForUser("p", user, domain...) |
| } |
| |
| // GetNamedPermissionsForUser gets permissions for a user or role by named policy. |
| func (e *Enforcer) GetNamedPermissionsForUser(ptype string, user string, domain ...string) ([][]string, error) { |
| permission := make([][]string, 0) |
| for pType, assertion := range e.model["p"] { |
| if pType != ptype { |
| continue |
| } |
| args := make([]string, len(assertion.Tokens)) |
| subIndex, err := e.GetFieldIndex("p", constant.SubjectIndex) |
| if err != nil { |
| subIndex = 0 |
| } |
| args[subIndex] = user |
| |
| if len(domain) > 0 { |
| var index int |
| index, err = e.GetFieldIndex(ptype, constant.DomainIndex) |
| if err != nil { |
| return permission, err |
| } |
| args[index] = domain[0] |
| } |
| perm, err := e.GetFilteredNamedPolicy(ptype, 0, args...) |
| if err != nil { |
| return permission, err |
| } |
| permission = append(permission, perm...) |
| } |
| return permission, nil |
| } |
| |
| // HasPermissionForUser determines whether a user has a permission. |
| func (e *Enforcer) HasPermissionForUser(user string, permission ...string) (bool, error) { |
| return e.HasPolicy(util.JoinSlice(user, permission...)) |
| } |
| |
| // GetImplicitRolesForUser gets implicit roles that a user has. |
| // Compared to GetRolesForUser(), this function retrieves indirect roles besides direct roles. |
| // For example: |
| // g, alice, role:admin |
| // g, role:admin, role:user |
| // |
| // GetRolesForUser("alice") can only get: ["role:admin"]. |
| // But GetImplicitRolesForUser("alice") will get: ["role:admin", "role:user"]. |
| func (e *Enforcer) GetImplicitRolesForUser(name string, domain ...string) ([]string, error) { |
| var res []string |
| |
| for rm := range e.rmMap { |
| roles, err := e.GetNamedImplicitRolesForUser(rm, name, domain...) |
| if err != nil { |
| return nil, err |
| } |
| res = append(res, roles...) |
| } |
| |
| for crm := range e.condRmMap { |
| roles, err := e.GetNamedImplicitRolesForUser(crm, name, domain...) |
| if err != nil { |
| return nil, err |
| } |
| res = append(res, roles...) |
| } |
| |
| return res, nil |
| } |
| |
| // GetNamedImplicitRolesForUser gets implicit roles that a user has by named role definition. |
| // Compared to GetImplicitRolesForUser(), this function retrieves indirect roles besides direct roles. |
| // For example: |
| // g, alice, role:admin |
| // g, role:admin, role:user |
| // g2, alice, role:admin2 |
| // |
| // GetImplicitRolesForUser("alice") can only get: ["role:admin", "role:user"]. |
| // But GetNamedImplicitRolesForUser("g2", "alice") will get: ["role:admin2"]. |
| func (e *Enforcer) GetNamedImplicitRolesForUser(ptype string, name string, domain ...string) ([]string, error) { |
| rm := e.GetNamedRoleManager(ptype) |
| if rm == nil { |
| return nil, fmt.Errorf("role manager %s is not initialized", ptype) |
| } |
| |
| // Use the role manager's GetImplicitRoles method which respects maxHierarchyLevel |
| return rm.GetImplicitRoles(name, domain...) |
| } |
| |
| // GetImplicitUsersForRole gets implicit users for a role. |
| func (e *Enforcer) GetImplicitUsersForRole(name string, domain ...string) ([]string, error) { |
| res := []string{} |
| var rms []rbac.RoleManager |
| |
| for _, rm := range e.rmMap { |
| rms = append(rms, rm) |
| } |
| for _, crm := range e.condRmMap { |
| rms = append(rms, crm) |
| } |
| |
| for _, rm := range rms { |
| // Use the role manager's GetImplicitUsers method which respects maxHierarchyLevel |
| users, err := rm.GetImplicitUsers(name, domain...) |
| if err != nil && err.Error() != "error: name does not exist" { |
| return nil, err |
| } |
| res = append(res, users...) |
| } |
| |
| return res, nil |
| } |
| |
| // GetImplicitPermissionsForUser gets implicit permissions for a user or role. |
| // Compared to GetPermissionsForUser(), this function retrieves permissions for inherited roles. |
| // For example: |
| // p, admin, data1, read |
| // p, alice, data2, read |
| // g, alice, admin |
| // |
| // GetPermissionsForUser("alice") can only get: [["alice", "data2", "read"]]. |
| // But GetImplicitPermissionsForUser("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]]. |
| func (e *Enforcer) GetImplicitPermissionsForUser(user string, domain ...string) ([][]string, error) { |
| return e.GetNamedImplicitPermissionsForUser("p", "g", user, domain...) |
| } |
| |
| // GetNamedImplicitPermissionsForUser gets implicit permissions for a user or role by named policy. |
| // Compared to GetNamedPermissionsForUser(), this function retrieves permissions for inherited roles. |
| // For example: |
| // p, admin, data1, read |
| // p2, admin, create |
| // g, alice, admin |
| // |
| // GetImplicitPermissionsForUser("alice") can only get: [["admin", "data1", "read"]], whose policy is default policy "p" |
| // But you can specify the named policy "p2" to get: [["admin", "create"]] by GetNamedImplicitPermissionsForUser("p2","alice"). |
| func (e *Enforcer) GetNamedImplicitPermissionsForUser(ptype string, gtype string, user string, domain ...string) ([][]string, error) { |
| permission := make([][]string, 0) |
| rm := e.GetNamedRoleManager(gtype) |
| if rm == nil { |
| return nil, fmt.Errorf("role manager %s is not initialized", gtype) |
| } |
| |
| roles, err := e.GetNamedImplicitRolesForUser(gtype, user, domain...) |
| if err != nil { |
| return nil, err |
| } |
| policyRoles := make(map[string]struct{}, len(roles)+1) |
| policyRoles[user] = struct{}{} |
| for _, r := range roles { |
| policyRoles[r] = struct{}{} |
| } |
| |
| domainIndex, err := e.GetFieldIndex(ptype, constant.DomainIndex) |
| for _, rule := range e.model["p"][ptype].Policy { |
| if len(domain) == 0 { |
| if _, ok := policyRoles[rule[0]]; ok { |
| permission = append(permission, deepCopyPolicy(rule)) |
| } |
| continue |
| } |
| if len(domain) > 1 { |
| return nil, errors.ErrDomainParameter |
| } |
| if err != nil { |
| return nil, err |
| } |
| d := domain[0] |
| matched := rm.Match(d, rule[domainIndex]) |
| if !matched { |
| continue |
| } |
| if _, ok := policyRoles[rule[0]]; ok { |
| newRule := deepCopyPolicy(rule) |
| newRule[domainIndex] = d |
| permission = append(permission, newRule) |
| } |
| } |
| return permission, nil |
| } |
| |
| // GetImplicitUsersForPermission gets implicit users for a permission. |
| // For example: |
| // p, admin, data1, read |
| // p, bob, data1, read |
| // g, alice, admin |
| // |
| // GetImplicitUsersForPermission("data1", "read") will get: ["alice", "bob"]. |
| // Note: only users will be returned, roles (2nd arg in "g") will be excluded. |
| func (e *Enforcer) GetImplicitUsersForPermission(permission ...string) ([]string, error) { |
| pSubjects, err := e.GetAllSubjects() |
| if err != nil { |
| return nil, err |
| } |
| gInherit, err := e.model.GetValuesForFieldInPolicyAllTypes("g", 1) |
| if err != nil { |
| return nil, err |
| } |
| gSubjects, err := e.model.GetValuesForFieldInPolicyAllTypes("g", 0) |
| if err != nil { |
| return nil, err |
| } |
| |
| subjects := append(pSubjects, gSubjects...) |
| util.ArrayRemoveDuplicates(&subjects) |
| |
| subjects = util.SetSubtract(subjects, gInherit) |
| |
| res := []string{} |
| for _, user := range subjects { |
| req := util.JoinSliceAny(user, permission...) |
| allowed, err := e.Enforce(req...) |
| if err != nil { |
| return nil, err |
| } |
| |
| if allowed { |
| res = append(res, user) |
| } |
| } |
| |
| return res, nil |
| } |
| |
| // GetDomainsForUser gets all domains. |
| func (e *Enforcer) GetDomainsForUser(user string) ([]string, error) { |
| var domains []string |
| for _, rm := range e.rmMap { |
| domain, err := rm.GetDomains(user) |
| if err != nil { |
| return nil, err |
| } |
| domains = append(domains, domain...) |
| } |
| for _, crm := range e.condRmMap { |
| domain, err := crm.GetDomains(user) |
| if err != nil { |
| return nil, err |
| } |
| domains = append(domains, domain...) |
| } |
| return domains, nil |
| } |
| |
| // GetImplicitResourcesForUser returns all policies that user obtaining in domain. |
| func (e *Enforcer) GetImplicitResourcesForUser(user string, domain ...string) ([][]string, error) { |
| permissions, err := e.GetImplicitPermissionsForUser(user, domain...) |
| if err != nil { |
| return nil, err |
| } |
| res := make([][]string, 0) |
| for _, permission := range permissions { |
| if permission[0] == user { |
| res = append(res, permission) |
| continue |
| } |
| resLocal := [][]string{{user}} |
| tokensLength := len(permission) |
| t := make([][]string, 1, tokensLength) |
| for _, token := range permission[1:] { |
| tokens, err := e.GetImplicitUsersForRole(token, domain...) |
| if err != nil { |
| return nil, err |
| } |
| tokens = append(tokens, token) |
| t = append(t, tokens) |
| } |
| for i := 1; i < tokensLength; i++ { |
| n := make([][]string, 0) |
| for _, tokens := range t[i] { |
| for _, policy := range resLocal { |
| t := append([]string(nil), policy...) |
| t = append(t, tokens) |
| n = append(n, t) |
| } |
| } |
| resLocal = n |
| } |
| res = append(res, resLocal...) |
| } |
| return res, nil |
| } |
| |
| // deepCopyPolicy returns a deepcopy version of the policy to prevent changing policies through returned slice. |
| func deepCopyPolicy(src []string) []string { |
| newRule := make([]string, len(src)) |
| copy(newRule, src) |
| return newRule |
| } |
| |
| // GetAllowedObjectConditions returns a string array of object conditions that the user can access. |
| // For example: conditions, err := e.GetAllowedObjectConditions("alice", "read", "r.obj.") |
| // Note: |
| // |
| // 0. prefix: You can customize the prefix of the object conditions, and "r.obj." is commonly used as a prefix. |
| // After removing the prefix, the remaining part is the condition of the object. |
| // If there is an obj policy that does not meet the prefix requirement, an errors.ERR_OBJ_CONDITION will be returned. |
| // |
| // 1. If the 'objectConditions' array is empty, return errors.ERR_EMPTY_CONDITION |
| // This error is returned because some data adapters' ORM return full table data by default |
| // when they receive an empty condition, which tends to behave contrary to expectations.(e.g. GORM) |
| // If you are using an adapter that does not behave like this, you can choose to ignore this error. |
| func (e *Enforcer) GetAllowedObjectConditions(user string, action string, prefix string) ([]string, error) { |
| permissions, err := e.GetImplicitPermissionsForUser(user) |
| if err != nil { |
| return nil, err |
| } |
| |
| var objectConditions []string |
| for _, policy := range permissions { |
| // policy {sub, obj, act} |
| if policy[2] == action { |
| if !strings.HasPrefix(policy[1], prefix) { |
| return nil, errors.ErrObjCondition |
| } |
| objectConditions = append(objectConditions, strings.TrimPrefix(policy[1], prefix)) |
| } |
| } |
| |
| if len(objectConditions) == 0 { |
| return nil, errors.ErrEmptyCondition |
| } |
| |
| return objectConditions, nil |
| } |
| |
| // removeDuplicatePermissions Convert permissions to string as a hash to deduplicate. |
| func removeDuplicatePermissions(permissions [][]string) [][]string { |
| permissionsSet := make(map[string]bool) |
| res := make([][]string, 0) |
| for _, permission := range permissions { |
| permissionStr := util.ArrayToString(permission) |
| if permissionsSet[permissionStr] { |
| continue |
| } |
| permissionsSet[permissionStr] = true |
| res = append(res, permission) |
| } |
| return res |
| } |
| |
| // GetImplicitUsersForResource return implicit user based on resource. |
| // for example: |
| // p, alice, data1, read |
| // p, bob, data2, write |
| // p, data2_admin, data2, read |
| // p, data2_admin, data2, write |
| // g, alice, data2_admin |
| // GetImplicitUsersForResource("data2") will return [[bob data2 write] [alice data2 read] [alice data2 write]] |
| // GetImplicitUsersForResource("data1") will return [[alice data1 read]] |
| // Note: only users will be returned, roles (2nd arg in "g") will be excluded. |
| func (e *Enforcer) GetImplicitUsersForResource(resource string) ([][]string, error) { |
| return e.GetNamedImplicitUsersForResource("g", resource) |
| } |
| |
| // GetNamedImplicitUsersForResource return implicit user based on resource with named policy support. |
| // This function handles resource role relationships through named policies (e.g., g2, g3, etc.). |
| // for example: |
| // p, admin_group, admin_data, * |
| // g, admin, admin_group |
| // g2, app, admin_data |
| // GetNamedImplicitUsersForResource("g2", "app") will return users who have access to admin_data through g2 relationship. |
| func (e *Enforcer) GetNamedImplicitUsersForResource(ptype string, resource string) ([][]string, error) { |
| permissions := make([][]string, 0) |
| subjectIndex, _ := e.GetFieldIndex("p", "sub") |
| objectIndex, _ := e.GetFieldIndex("p", "obj") |
| rm := e.GetRoleManager() |
| if rm == nil { |
| return nil, fmt.Errorf("role manager is not initialized") |
| } |
| |
| isRole := make(map[string]bool) |
| roles, err := e.GetAllRoles() |
| if err != nil { |
| return nil, err |
| } |
| for _, role := range roles { |
| isRole[role] = true |
| } |
| |
| // Get all resource types that the resource can access through ptype (e.g., g2) |
| ptypePolicies, _ := e.GetNamedGroupingPolicy(ptype) |
| resourceAccessibleResourceTypes := make(map[string]bool) |
| |
| for _, ptypePolicy := range ptypePolicies { |
| if ptypePolicy[0] == resource { // ptypePolicy[0] is the resource |
| resourceAccessibleResourceTypes[ptypePolicy[1]] = true // ptypePolicy[1] is the resource type it can access |
| } |
| } |
| |
| for _, rule := range e.model["p"]["p"].Policy { |
| obj := rule[objectIndex] |
| sub := rule[subjectIndex] |
| |
| // Check if this policy is directly for the resource OR for a resource type the resource can access |
| if obj == resource || resourceAccessibleResourceTypes[obj] { |
| if !isRole[sub] { |
| permissions = append(permissions, rule) |
| } else { |
| users, err := rm.GetUsers(sub) |
| if err != nil { |
| continue |
| } |
| |
| for _, user := range users { |
| implicitUserRule := deepCopyPolicy(rule) |
| implicitUserRule[subjectIndex] = user |
| permissions = append(permissions, implicitUserRule) |
| } |
| } |
| } |
| } |
| |
| res := removeDuplicatePermissions(permissions) |
| return res, nil |
| } |
| |
| // GetImplicitUsersForResourceByDomain return implicit user based on resource and domain. |
| // Compared to GetImplicitUsersForResource, domain is supported. |
| func (e *Enforcer) GetImplicitUsersForResourceByDomain(resource string, domain string) ([][]string, error) { |
| permissions := make([][]string, 0) |
| subjectIndex, _ := e.GetFieldIndex("p", "sub") |
| objectIndex, _ := e.GetFieldIndex("p", "obj") |
| domIndex, _ := e.GetFieldIndex("p", "dom") |
| rm := e.GetRoleManager() |
| if rm == nil { |
| return nil, fmt.Errorf("role manager is not initialized") |
| } |
| |
| isRole := make(map[string]bool) |
| |
| if roles, err := e.GetAllRolesByDomain(domain); err != nil { |
| return nil, err |
| } else { |
| for _, role := range roles { |
| isRole[role] = true |
| } |
| } |
| |
| for _, rule := range e.model["p"]["p"].Policy { |
| obj := rule[objectIndex] |
| if obj != resource { |
| continue |
| } |
| |
| sub := rule[subjectIndex] |
| |
| if !isRole[sub] { |
| permissions = append(permissions, rule) |
| } else { |
| if domain != rule[domIndex] { |
| continue |
| } |
| users, err := rm.GetUsers(sub, domain) |
| if err != nil { |
| return nil, err |
| } |
| |
| for _, user := range users { |
| implicitUserRule := deepCopyPolicy(rule) |
| implicitUserRule[subjectIndex] = user |
| permissions = append(permissions, implicitUserRule) |
| } |
| } |
| } |
| |
| res := removeDuplicatePermissions(permissions) |
| return res, nil |
| } |
| |
| // GetImplicitObjectPatternsForUser returns all object patterns (with wildcards) that a user has for a given domain and action. |
| // For example: |
| // p, admin, chronicle/123, location/*, read |
| // p, user, chronicle/456, location/789, read |
| // g, alice, admin |
| // g, bob, user |
| // |
| // GetImplicitObjectPatternsForUser("alice", "chronicle/123", "read") will return ["location/*"]. |
| // GetImplicitObjectPatternsForUser("bob", "chronicle/456", "read") will return ["location/789"]. |
| func (e *Enforcer) GetImplicitObjectPatternsForUser(user string, domain string, action string) ([]string, error) { |
| roles, err := e.GetImplicitRolesForUser(user, domain) |
| if err != nil { |
| return nil, err |
| } |
| |
| subjects := append([]string{user}, roles...) |
| subjectIndex, _ := e.GetFieldIndex("p", constant.SubjectIndex) |
| domainIndex, _ := e.GetFieldIndex("p", constant.DomainIndex) |
| objectIndex, _ := e.GetFieldIndex("p", constant.ObjectIndex) |
| actionIndex, _ := e.GetFieldIndex("p", constant.ActionIndex) |
| |
| patterns := make(map[string]struct{}) |
| for _, rule := range e.model["p"]["p"].Policy { |
| sub := rule[subjectIndex] |
| matched := false |
| for _, subject := range subjects { |
| if sub == subject { |
| matched = true |
| break |
| } |
| } |
| if !matched { |
| continue |
| } |
| |
| if !e.matchDomain(domainIndex, domain, rule) { |
| continue |
| } |
| |
| ruleAction := rule[actionIndex] |
| if ruleAction != action && ruleAction != "*" { |
| continue |
| } |
| |
| obj := rule[objectIndex] |
| patterns[obj] = struct{}{} |
| } |
| |
| result := make([]string, 0, len(patterns)) |
| for pattern := range patterns { |
| result = append(result, pattern) |
| } |
| |
| return result, nil |
| } |
| |
| // matchDomain checks if the domain matches the rule domain using pattern matching. |
| func (e *Enforcer) matchDomain(domainIndex int, domain string, rule []string) bool { |
| if domainIndex < 0 || domain == "" { |
| return true |
| } |
| ruleDomain := rule[domainIndex] |
| if ruleDomain == domain { |
| return true |
| } |
| for _, rm := range e.rmMap { |
| if rm.Match(domain, ruleDomain) { |
| return true |
| } |
| } |
| for _, crm := range e.condRmMap { |
| if crm.Match(domain, ruleDomain) { |
| return true |
| } |
| } |
| return false |
| } |