laravel-authz icon indicating copy to clipboard operation
laravel-authz copied to clipboard

array_combine error with different request and policy definitions

Open swarakaka opened this issue 1 year ago • 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 avatar Dec 12 '24 10:12 swarakaka

Hello @leeqvip, could you please review this issue?

swarakaka avatar Dec 12 '24 11:12 swarakaka

@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?

leeqvip avatar Dec 12 '24 16:12 leeqvip

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"]]]

swarakaka avatar Dec 12 '24 16:12 swarakaka

@swarakaka

["admin","Brand","name","read","allow","system"]

Some policies have 6 columns, but your model configuration only has 5 parameters

leeqvip avatar Dec 13 '24 17:12 leeqvip

@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 avatar Dec 14 '24 09:12 swarakaka

@swarakaka So you need to modify your model or delete the policies that do not comply

leeqvip avatar Dec 14 '24 12:12 leeqvip

@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 avatar Dec 14 '24 12:12 swarakaka

@swarakaka If you have multiple enforcers, different enforcers should use different adapters or data tables.

leeqvip avatar Dec 14 '24 12:12 leeqvip

@leeqvip

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;
            });
        });

swarakaka avatar Dec 14 '24 13:12 swarakaka

Do you want to determine the role inheritance relationship? You can try getImplicitRolesForUser or getRolesForUser?

leeqvip avatar Dec 14 '24 14:12 leeqvip

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.

swarakaka avatar Dec 14 '24 15:12 swarakaka

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 ...

leeqvip avatar Dec 14 '24 16:12 leeqvip

@leeqvip I don't know if the problem is related to roles and permissions. But I want to give the permissions directly to the roles. Users also have one or more roles.

swarakaka avatar Dec 14 '24 18:12 swarakaka