blob: a5d4a14c7266b907d918824d506f74fe181553df [file] [log] [blame]
--Copyright 2021 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.
local ManagementEnforcer = require("src.main.ManagementEnforcer")
local Util = require("src.util.Util")
-- Enforcer = ManagementEnforcer + RBAC API.
local Enforcer = {}
setmetatable(Enforcer, ManagementEnforcer)
Enforcer.__index = Enforcer
-- GetRolesForUser gets the roles that a user has.
function Enforcer:GetRolesForUser(name, ...)
return self.model.model["g"]["g"].RM:getRoles(name, ...)
end
-- GetUsersForRole gets the users that has a role.
function Enforcer:GetUsersForRole(name, ...)
return self.model.model["g"]["g"].RM:getUsers(name, ...)
end
-- HasRoleForUser determines whether a user has a role.
function Enforcer:HasRoleForUser(name, role, ...)
local roles = self:GetRolesForUser(name, ...)
local hasRole = false
for _, r in pairs(roles) do
if r == role then
hasRole = true
break
end
end
return hasRole
end
-- AddRoleForUser adds role for a user.
-- Returns false if the user already has the roles (aka not affected).
function Enforcer:AddRoleForUser(user, role, ...)
local args = {...}
table.insert(args, 1, role)
table.insert(args, 1, user)
return self:AddGroupingPolicy(args)
end
-- AddRolesForUser adds roles for a user.
-- Returns false if the user already has the roles (aka not affected).
function Enforcer:AddRolesForUser(user, roles, ...)
local rules = {}
for _, role in pairs(roles) do
local rule = {user, role, ...}
table.insert(rules, rule)
end
return self:AddGroupingPolicies(rules)
end
-- DeleteRoleForUser deletes a role for a user.
-- Returns false if the user does not have the role (aka not affected).
function Enforcer:DeleteRoleForUser(user, role, ...)
local args = {...}
table.insert(args, 1, role)
table.insert(args, 1, user)
return self:RemoveGroupingPolicy(args)
end
-- DeleteRolesForUser deletes all roles for a user.
-- Returns false if the user does not have any roles (aka not affected).
function Enforcer:DeleteRolesForUser(user, ...)
if #{...} == 0 then
return self:RemoveFilteredGroupingPolicy(0, user)
elseif #{...} > 1 then
return false
else
local domain = {...}
return self:RemoveFilteredGroupingPolicy(0, user, "", domain[1])
end
end
-- DeleteUser deletes a user.
-- Returns false if the user does not exist (aka not affected).
function Enforcer:DeleteUser(user)
local res1 = self:RemoveFilteredGroupingPolicy(0, user)
local res2 = self:RemoveFilteredPolicy(0, user)
return res1 or res2
end
-- DeleteRole deletes a role.
-- Returns false if the user does not exist (aka not affected).
function Enforcer:DeleteRole(role)
local res1 = self:RemoveFilteredGroupingPolicy(1, role)
local res2 = self:RemoveFilteredPolicy(0, role)
return res1 or res2
end
-- DeletePermission deletes a permission.
-- Returns false if the permission does not exist (aka not affected).
function Enforcer:DeletePermission(...)
return self:RemoveFilteredPolicy(1, ...)
end
-- AddPermissionForUser deletes a permission.
-- Returns false if the permission does not exist (aka not affected).
function Enforcer:AddPermissionForUser(user, ...)
return self:AddPolicy(user, ...)
end
-- DeletePermissionForUser deletes a permission for a user or role.
-- Returns false if the permission does not exist (aka not affected).
function Enforcer:DeletePermissionForUser(user, ...)
return self:RemovePolicy(user, ...)
end
-- DeletePermissionsForUser deletes permissions for a user or role.
-- Returns false if the permission does not exist (aka not affected).
function Enforcer:DeletePermissionsForUser(user)
return self:RemoveFilteredPolicy(0, user)
end
-- GetPermissionsForUser gets permissions for a user or role.
function Enforcer:GetPermissionsForUser(user, ...)
local permissions = {}
for ptype, ast in pairs(self.model.model["p"]) do
local args = {}
for _ = 1, #ast.tokens do
table.insert(args, "")
end
args[1] = user
if #{...}>0 then
local index = self:getDomainIndex(ptype)
if index < #ast.tokens then
local domain = {...}
args[index] = domain[1]
end
end
local perm = self:GetFilteredPolicy(0, args)
for _, v in pairs(perm) do
table.insert(permissions, v)
end
end
return permissions
end
-- HasPermissionForUser determines whether a user has a permission.
function Enforcer:HasPermissionForUser(user, ...)
return self:HasPolicy(user, ...)
end
-- 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"].
function Enforcer:GetImplicitRolesForUser(name, ...)
local res = {}
local roleSet = {}
roleSet[name] = true
local q = {}
table.insert(q, name)
while #q>0 do
local n = q[1]
table.remove(q, 1)
for _, rm in pairs(self.rmMap) do
local roles = rm:getRoles(n, ...)
for _, r in pairs(roles) do
if not roleSet[r] then
table.insert(res, r)
table.insert(q, r)
roleSet[r] = true
end
end
end
end
return res
end
-- GetImplicitUsersForRole gets implicit users for a role.
function Enforcer:GetImplicitUsersForRole(name, ...)
local res = {}
local roleSet = {}
roleSet[name] = true
local q = {}
table.insert(q, name)
while #q>0 do
local n = q[1]
table.remove(q, 1)
for _, rm in pairs(self.rmMap) do
local roles = rm:getUsers(n, ...)
for _, r in pairs(roles) do
if not roleSet[r] then
table.insert(res, r)
table.insert(q, r)
roleSet[r] = true
end
end
end
end
return res
end
-- 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"]].
function Enforcer:GetImplicitPermissionsForUser(user, ...)
local roles = self:GetImplicitRolesForUser(user, ...)
table.insert(roles, 1, user)
local res = {}
local permissions
for _, role in pairs(roles) do
permissions = self:GetPermissionsForUser(role, ...)
for _, v in pairs(permissions) do
table.insert(res, v)
end
end
return res
end
-- 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.
function Enforcer:GetImplicitUsersForPermission(...)
local pSubjects = self:GetAllSubjects()
local gInherit = self.model:getValuesForFieldInPolicyAllTypes("g", 2)
local gSubjects = self.model:getValuesForFieldInPolicyAllTypes("g", 1)
local subjects = {}
for _, v in pairs(pSubjects) do
table.insert(subjects, v)
end
for _, v in pairs(gSubjects) do
table.insert(subjects, v)
end
subjects = Util.arrayRemoveDuplications(subjects)
subjects = Util.setSubtract(subjects, gInherit)
local res = {}
for _, user in pairs(subjects) do
local allowed = self:enforce(user, ...)
if allowed then
table.insert(res, user)
end
end
return res
end
-- GetDomainsForUser gets all domains
function Enforcer:GetDomainsForUser(user)
local domains = {}
for _, rm in pairs(self.rmMap) do
local domain = self:GetDomains(user)
for _, v in pairs(domain) do
table.insert(domains, v)
end
end
end
-- GetImplicitResourcesForUser returns all policies that user obtaining in domain
function Enforcer:GetImplicitResourcesForUser(user, ...)
local permissions = self:GetImplicitPermissionsForUser(user, ...)
local res = {}
for _, permission in pairs(permissions) do
if permission[1] == user then
table.insert(res, permission)
else
local resLocal = {{user}}
local tokensLength = #permission
local t = {{}}
for i = 2, tokensLength do
local tokens = self:GetImplicitUsersForRole(permission[i], ...)
table.insert(tokens, permission[i])
table.insert(t, tokens)
end
for i = 2, tokensLength do
local n = {}
for _, tokens in pairs(t[i]) do
for _, policy in pairs(resLocal) do
local tks = {}
for _, p in pairs(policy) do
table.insert(tks, p)
end
table.insert(tks, tokens)
table.insert(n, tks)
end
end
resLocal = n
end
for _, r in pairs(resLocal) do
table.insert(res, r)
end
end
end
return res
end
-- RBAC API with domains
-- GetUsersForRoleInDomain gets the users that has a role inside a domain.
function Enforcer:GetUsersForRoleInDomain(name, domain)
local res, _ = self.model.model["g"]["g"].RM:getUsers(name, domain)
return res
end
-- GetRolesForUserInDomain gets the roles that a user has inside a domain.
function Enforcer:GetRolesForUserInDomain(name, domain)
local res, _ = self.model.model["g"]["g"].RM:getRoles(name, domain)
return res
end
-- GetPermissionsForUserInDomain gets permissions for a user or role inside a domain.
function Enforcer:GetPermissionsForUserInDomain(user, domain)
return self:GetFilteredPolicy(0, user, domain)
end
-- AddRoleForUserInDomain adds a role for a user inside a domain.
-- Returns false if the user already has the role (aka not affected).
function Enforcer:AddRoleForUserInDomain(user, role, domain)
return self:AddGroupingPolicy(user, role, domain)
end
-- DeleteRoleForUserInDomain deletes a role for a user inside a domain.
-- Returns false if the user does not have the role (aka not affected).
function Enforcer:DeleteRoleForUserInDomain(user, role, domain)
return self:RemoveGroupingPolicy(user, role, domain)
end
-- DeleteRolesForUserInDomain deletes all roles for a user inside a domain.
-- Returns false if the user does not have any roles (aka not affected).
function Enforcer:DeleteRolesForUserInDomain(user, domain)
local roles = self.model.model["g"]["g"].RM:getRoles(user, domain)
local rules = {}
for _, role in pairs(roles) do
table.insert(rules, {user, role, domain})
end
return self:RemoveGroupingPolicies(rules)
end
-- GetAllUsersByDomain would get all users associated with the domain.
function Enforcer:GetAllUsersByDomain(domain)
local m = {}
local g = self.model.model["g"]["g"]
local p = self.model.model["p"]["p"]
local users = {}
local inx = self:getDomainIndex("p")
local function getUser(index, policies, dom, x)
if #policies == 0 or #policies[1] < index then
return {}
end
local res = {}
for _, policy in pairs(policies) do
if not x[policy[1]] and policy[index] == dom then
table.insert(res, policy[1])
x[policy[1]] = {}
end
end
return res
end
local gUsers = getUser(3, g.policy, domain, m)
for _, v in pairs(gUsers) do
table.insert(users, v)
end
local pUsers = getUser(inx, p.policy, domain, m)
for _, v in pairs(pUsers) do
table.insert(users, v)
end
return users
end
-- DeleteAllUsersByDomain would delete all users associated with the domain.
function Enforcer:DeleteAllUsersByDomain(domain)
local g = self.model.model["g"]["g"]
local p = self.model.model["p"]["p"]
local inx = self:getDomainIndex("p")
local function getUser(index, policies, dom)
if #policies == 0 or #policies[1] < index then
return {}
end
local res = {}
for _, policy in pairs(policies) do
if policy[index] == dom then
table.insert(res, policy)
end
end
return res
end
local gUsers = getUser(3, g.policy, domain)
self:RemoveGroupingPolicies(gUsers)
local pUsers = getUser(inx, p.policy, domain)
self:RemovePolicies(pUsers)
return true
end
-- DeleteDomains would delete all associated users and roles.
-- It would delete all domains if parameter is not provided.
function Enforcer:DeleteDomains(...)
local domains = {...}
if #domains == 0 then
self:clearPolicy()
end
for _, domain in pairs(domains) do
self:DeleteAllUsersByDomain(domain)
end
return true
end
return Enforcer