php-casbin / laravel-authz

An authorization library that supports access control models like ACL, RBAC, ABAC in Laravel.
Apache License 2.0
272 stars 46 forks source link

root for rbac with all pattern model can not pass the verify. But the casbin editor does. #59

Closed oknixus closed 1 year ago

oknixus commented 1 year ago

My codes:

    // adds permissions to a user
    Enforcer::addPermissionForUser('admin', 'article', 'content', 'read');
    Enforcer::addPermissionForUser('admin', 'goods', 'content', 'write');

    Enforcer::addPermissionForUser('root', '*', '*', '*');

    // adds a role for a user.
    Enforcer::addRoleForUser('eve', 'root', '*');
    Enforcer::addRoleForUser('bob', 'admin', '*');
    Enforcer::addRoleForUser('tom', 'admin', 'goods');

    if (Enforcer::enforce("eve", "article", "content", "read")) {
        return sprintf('yes. %s', now()->format('Y-m-d H:i:s'));
    }

    if (Enforcer::enforce("bob", 'goods', 'content', 'read')) {
        return sprintf('bob has this perm. %s', now()->format('Y-m-d H:i:s'));
    }

    if (Enforcer::enforce('tom', 'goods', 'content', 'write')) {
        return sprintf('this is tom. %s', now()->format('Y-m-d H:i:s'));
    }

Enforcement result in my requests, only the last one without * passed enforcement:

image

In the casbin editor:

image

I found the dom can't use the pattern.

If I change the code to(*_use '' instead of 'article'_**):

    if (Enforcer::enforce("eve", "*", "content", "read")) {
        return sprintf('yes. %s', now()->format('Y-m-d H:i:s'));
    }

It works fine:

image
hsluoyz commented 1 year ago

@oknixus this is possible because Casbin Editor is powered by Node.js version Casbin: https://github.com/casbin/casbin-editor , however, this repo is powered by PHP version Casbin

@leeqvip any ideas?

oknixus commented 1 year ago

Thanks very much!

oknixus commented 1 year ago

I could implement the global super user permission via Enforcer::hasRoleForUser($userId, 'root', '*'), but can't implement the local super user permission. eg: There are two module named article and goods, and the admin role has their privileges. One user need get All the privileges of the admin.

Would you being to finish it ? Or some suggestions? Thanks again.

oknixus commented 1 year ago

I add this !Enforcer::enforce($userId, '*', $model, $action) in the middleware, implement the local super user permissions.

Then the whole conditions:

        if (
            (
                !Enforcer::enforce($userId, $module, $model, $action)
                && !Enforcer::enforce($userId, '*', $model, $action)
            )
            && !Enforcer::hasRoleForUser($userId, 'root', '*')
        ) {
            return \response()->json(['msg' => '无操作权限']);
        }
hsluoyz commented 1 year ago

@oknixus glad to see that you have resolved the issue. Why open again?

oknixus commented 1 year ago

I resolved too rough. Expect your elegant solution.😄

oknixus commented 1 year ago

Well……I'd better close this issue. Thanks very much.

leeqvip commented 1 year ago

@oknixus refer to this: Super Admin

leeqvip commented 1 year ago

@oknixus Can you check whether your model configuration is correct? I wrote a demo using php-casbin, and the result is as expected.

<?php
require_once './vendor/autoload.php';

use Casbin\Enforcer;
use Casbin\Model\Model;

$model = Model::newModelFromString(
    <<<EOT
    [request_definition]
    r = sub, dom, obj, act

    [policy_definition]
    p = sub, dom, obj, act

    [role_definition]
    g = _, _, _

    [policy_effect]
    e = some(where (p.eft == allow))

    [matchers]
    m = g(r.sub, p.sub, r.dom) && keyMatch2(r.obj, p.obj) && keyMatch2(r.act, p.act) || p.act == "*"
    EOT
);

$e = new Enforcer($model);

// adds permissions to a user
$e->addPermissionForUser('admin', 'article', 'content', 'read');
$e->addPermissionForUser('admin', 'goods', 'content', 'write');
$e->addPermissionForUser('root', '*', '*', '*');
// adds a role for a user.
$e->addRoleForUser('eve', 'root', '*');
$e->addRoleForUser('bob', 'admin', '*');
$e->addRoleForUser('tom', 'admin', 'goods');

if ($e->enforce("eve", "article", "content", "read")) {
    echo sprintf('yes. %s'.PHP_EOL, now()->format('Y-m-d H:i:s'));
}

if ($e->enforce("bob", 'goods', 'content', 'read')) {
    echo sprintf('bob has this perm. %s'.PHP_EOL, now()->format('Y-m-d H:i:s'));
}

if ($e->enforce('tom', 'goods', 'content', 'write')) {
    echo sprintf('this is tom. %s'.PHP_EOL, now()->format('Y-m-d H:i:s'));
}

Actual results:

# php index.php 
yes. 2023-03-23 15:58:21
bob has this perm. 2023-03-23 15:58:21
this is tom. 2023-03-23 15:58:21
oknixus commented 1 year ago

@leeqvip No. I'm afraid there's a problem in your matchers: The admin only have the permission write for goods. In your matchers, bob have read permission for the content of goods. This expends the permissions of bob.

oknixus commented 1 year ago

Well……my code also is wrong:

if (
            (
                !Enforcer::enforce($userId, $module, $model, $action)
                && !Enforcer::enforce($userId, '*', $model, $action)
            )
            && !Enforcer::hasRoleForUser($userId, 'root', '*')
        ) {
            return \response()->json(['msg' => '无操作权限']);
        }
oknixus commented 1 year ago

I think my matchers is wrong. This package is ok. @leeqvip Thanks your codes help me found the error.