array_combine error with different request and policy definitions
Closed this issue · 13 comments
Hello everyone!
I'm implementing role-based access control in my Laravel application using php-casbin/laravel-authz. I'm encountering an error when trying to enforce policies using a custom model where request and policy definitions have different numbers of parameters.
My model configuration:
[request_definition]
r = sub, obj, act, dom
[policy_definition]
p = sub, obj, act, eft, dom
[role_definition]
g = _, _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.act
The error I'm getting is:
array_combine(): Argument #1 ($keys) and argument #2 ($values) must have the same number of elements
This occurs in CoreEnforcer.php:761 when calling enforce(). I'm using a guarded enforcer like this:
$enforcer = Enforcer::guard('controller');
$hasPermission = $enforcer->enforce($role, $controller, $method, $domain);
This is a practical working example.
related issue #127
@swarakaka This is probably not a problem with php-casbin itself.
Can you debug and see if laravel-authz has problems loading policies? Can you getPolicy() and print it?
Yes, all the policies are successfully returning. even for the user.
$policies = collect($enforcer->getPolicy());
Log::info("policies: ", [$policies->all()]);
[2024-12-12 16:35:21] local.INFO: policies: [[["admin","Brand","name","read","allow","system"],["admin","Brand","name","write","allow","system"],["admin","Brand","name","update","allow","system"],["admin","Brand","name","delete","allow","system"],["admin","User","username","read","allow","system"],["admin","User","username","write","allow","system"],["admin","User","username","update","allow","system"],["admin","User","username","delete","allow","system"],["admin","User","email","read","allow","system"],["admin","User","email","write","allow","system"],["admin","User","email","update","allow","system"],["admin","User","email","delete","allow","system"],["admin","User","password","read","allow","system"],["admin","User","password","write","allow","system"],["admin","User","password","update","allow","system"],["admin","User","password","delete","allow","system"],["admin","User","tenant","read","allow","system"],["admin","User","tenant","write","allow","system"],["admin","User","tenant","update","allow","system"],["admin","User","tenant","delete","allow","system"],["admin","Role","name","read","allow","system"],["admin","Role","name","write","allow","system"],["admin","Role","name","update","allow","system"],["admin","Role","name","delete","allow","system"],["admin","Role","description","read","allow","system"],["admin","Role","description","write","allow","system"],["admin","Role","description","update","allow","system"],["admin","Role","description","delete","allow","system"],["admin","City","name","read","allow","system"],["admin","City","name","write","allow","system"],["admin","City","name","update","deny","system"],["admin","City","name","delete","deny","system"],["admin","City","post_code","read","allow","system"],["admin","City","post_code","write","allow","system"],["admin","City","post_code","update","deny","system"],["admin","City","post_code","delete","deny","system"],["admin","City","province_id","read","allow","system"],["admin","City","province_id","write","allow","system"],["admin","City","province_id","update","deny","system"],["admin","City","province_id","delete","deny","system"],["admin","City","longitude","read","allow","system"],["admin","City","longitude","write","allow","system"],["admin","City","longitude","update","deny","system"],["admin","City","longitude","delete","deny","system"],["admin","City","latitude","read","allow","system"],["admin","City","latitude","write","allow","system"],["admin","City","latitude","update","deny","system"],["admin","City","latitude","delete","deny","system"],["admin","City","created_by","read","allow","system"],["admin","City","created_by","write","allow","system"],["admin","City","created_by","update","deny","system"],["admin","City","created_by","delete","deny","system"],["admin","City","updated_by","read","allow","system"],["admin","City","updated_by","write","allow","system"],["admin","City","updated_by","update","deny","system"],["admin","City","updated_by","delete","deny","system"],["admin","City","deleted_by","read","allow","system"],["admin","City","deleted_by","write","allow","system"],["admin","City","deleted_by","update","deny","system"],["admin","City","deleted_by","delete","deny","system"],["admin","UsersController","index","allow","system"],["admin","UsersController","store","allow","system"],["admin","UsersController","show","allow","system"],["admin","UsersController","update","allow","system"],["admin","UsersController","destroy","allow","system"],["admin","UsersController","permissions","allow","system"],["admin","UsersController","assign","allow","system"],["admin","BrandsController","index","deny","system"],["admin","BrandsController","store","deny","system"],["admin","BrandsController","update","deny","system"],["admin","BrandsController","destroy","deny","system"],["admin","CitiesController","index","deny","system"],["admin","CitiesController","store","deny","system"],["admin","CitiesController","update","deny","system"],["admin","CitiesController","destroy","deny","system"],["admin","CountriesController","index","deny","system"],["admin","CountriesController","store","deny","system"],["admin","CountriesController","update","deny","system"],["admin","CountriesController","destroy","deny","system"],["admin","PoliciesController","index","deny","system"],["admin","PoliciesController","getAllRoles","deny","system"],["admin","PoliciesController","getModels","deny","system"],["admin","PoliciesController","getAttributes","deny","system"],["admin","PoliciesController","rolePermissionsByModel","deny","system"],["admin","PoliciesController","getControllers","deny","system"],["admin","PoliciesController","getControllerActions","deny","system"],["admin","PoliciesController","rolePermissionsByController","deny","system"],["admin","PoliciesController","createRole","deny","system"],["admin","PoliciesController","storeRolePermissionsByModel","deny","system"],["admin","PoliciesController","storeControllerPermissions","deny","system"]]]
["admin","Brand","name","read","allow","system"]
Some policies have 6 columns, but your model configuration only has 5 parameters
@leeqvip
Yes it is true that some policies have 6 columns but I use two different models. As shown in the code, I am using the controller guard.
$enforcer = Enforcer::guard('controller');
$hasPermission = $enforcer->enforce($role, $controller, $method, $domain);
controller model:
[request_definition]
r = sub, obj, act, dom
[policy_definition]
p = sub, obj, act, eft, dom
[role_definition]
g = _, _, _
[policy_effect]
e = some(where (p.eft == allow)
[matchers]
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.act
@swarakaka So you need to modify your model or delete the policies that do not comply
@leeqvip
What do you mean by modifying the model? Which model, the controller or the base one?
So you can't have two different models and each check according to the columns in the rules table?
@swarakaka If you have multiple enforcers, different enforcers should use different adapters or data tables.
Thank you very much for your reply. That's a good way. I found another solution, which compares all polices by roles:
return $roles->contains(function ($role) use ($enforcer, $resource, $action, $tenant) {
$policies = collect($enforcer->getImplicitPermissionsForUser($role))->filter(function ($policy) {
return is_array($policy) && count($policy) === 5;
});
if ($policies->isEmpty()) {
return false;
}
return $policies->contains(function ($policy) use ($role, $resource, $action, $tenant) {
return $policy[0] === $role
&& $policy[1] === $resource
&& $policy[2] === $action
&& $policy[3] === "allow"
&& $policy[4] === $tenant;
});
});
Do you want to determine the role inheritance relationship? You can try getImplicitRolesForUser or getRolesForUser?
No. Because I’ve already got the roles.
$roles = collect($enforcer->getImplicitRolesForUser($identifier, $tenant));
As I described the problem above. I can't do my comparison with Enforcer::enforce(), hence I do my comparison with cops.
If you want to decide whether a role has direct permissions, you can modify the expression configured in the model.
m = g(r.sub, p.sub, r.dom) ... to m = r.sub == p.sub ...