Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

array_combine error with different request and policy definitions #78

Open
swarakaka opened this issue Dec 12, 2024 · 13 comments
Open

array_combine error with different request and policy definitions #78

swarakaka opened this issue Dec 12, 2024 · 13 comments

Comments

@swarakaka
Copy link
Contributor

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
Copy link
Contributor Author

Hello @leeqvip,
could you please review this issue?

@leeqvip
Copy link
Member

leeqvip commented Dec 12, 2024

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

@swarakaka
Copy link
Contributor Author

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

@leeqvip
Copy link
Member

leeqvip commented Dec 13, 2024

@swarakaka

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

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

@swarakaka
Copy link
Contributor Author

swarakaka commented Dec 14, 2024

@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

@leeqvip
Copy link
Member

leeqvip commented Dec 14, 2024

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

@swarakaka
Copy link
Contributor Author

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

@leeqvip
Copy link
Member

leeqvip commented Dec 14, 2024

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

@swarakaka
Copy link
Contributor Author

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

@leeqvip
Copy link
Member

leeqvip commented Dec 14, 2024

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

@swarakaka
Copy link
Contributor Author

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.

@leeqvip
Copy link
Member

leeqvip commented Dec 14, 2024

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

@swarakaka
Copy link
Contributor Author

swarakaka commented Dec 14, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants