Zend Acl - возможно ли для утверждения разрешить доступ к привилегии, когда правила acl возвращают false?

По умолчанию возврат false в утверждении запрещает доступ, даже если это разрешено правилами acl. Я хочу сделать наоборот - то есть вернуть true в утверждении, чтобы разрешить доступ, когда правила acl это запрещают.

Например:

class TestAssert implements Zend_Acl_Assert_Interface
{
    public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $role = null, Zend_Acl_Resource_Interface $resource = null,
                           $privilege = null)
    {
        return true;
    }
}

$acl = new Zend_Acl;
$acl->addResource('page');
$acl->addRole('user');

$acl->allow('user', 'page', 'read', new TestAssert);
$acl->isAllowed('user', 'page', 'write');

Вышеупомянутая isAllowed () вернет false, потому что привилегия, о которой я спрашиваю, не разрешена в правилах acl, поэтому это не доходит до утверждения.

Возможно ли то, что я хочу?

Причина, по которой я хочу это сделать, заключается в том, что у пользователя могут быть определенные привилегии для всех страниц, а затем другой набор привилегий для страниц, которые они создали - при запросе привилегии я хочу иметь возможность определить, принадлежит ли страница им, и если то есть применять правила для «собственной страницы», а не «страницы». Очевидно, что в реальном приложении объекты пользователя и страницы передаются вместо строк.

ОБНОВЛЕНИЕ: мне удалось сделать то, что я хочу, создав подкласс Zend_Acl.

Этот класс позволяет добавлять обратные вызовы для определенных комбинаций ролей и ресурсов. Когда вызывается isAllowed (), выполняется обратный вызов, если он существует. Он передается с теми же параметрами, что и утверждение (а также результат parent :: isAllowed ()). Возвращаемое значение этого обратного вызова возвращается из isAllowed (), если оно не равно нулю, и в этом случае используется нормальное возвращаемое значение.

class Acl extends Zend_Acl
{
    protected $_callbacks = array();

    /**
     * Takes into account the callback to determine whether the role is allowed access
     * 
     * @param Zend_Acl_Role_Interface $role
     * @param Zend_Acl_Resource_Interface $resource
     * @param string $privilege
     * @return bool
     */
    public function isAllowed($role = null, $resource = null, $privilege = null)
    {
        $result = parent::isAllowed($role, $resource, $privilege);
        $role = $this->getRole($role)->getRoleId();
        $resource = $this->get($resource)->getResourceId();

        if(isset($this->_callbacks[$role][$resource]))
        {           
            $callbackResult = call_user_func($this->_callbacks[$role][$resource], $this, $role, $resource, $privilege, $result);
        }

        return isset($callbackResult) ? $callbackResult : $result;
    }

    /**
     * Add a callback for a specific role and resource combination.
     * If the callback returns a value, this is used as the return value for isAllowed().
     * Otherwise, if the callback returns null, the normal result of isAllowed() will be used.
     * 
     * @param Zend_Acl_Role_Interface $role
     * @param Zend_Acl_Resource_Interface $resource
     * @param callback $callback 
     */
    public function addCallback($role, $resource, $callback)
    {
        $role = $this->getRole($role)->getRoleId();
        $resource = $this->get($resource)->getResourceId();
        $this->_callbacks[$role][$resource] = $callback;
    }
}

Использование:

$acl = new Acl;
$acl->addResource('page');
$acl->addRole('user');

$acl->addCallback('user', 'page', function($acl, $role, $resource, $privilege, $result)
{
    return true;
});


$acl->allow('user', 'page', array('read'));
$acl->isAllowed('user', 'page', 'edit'); //returns true even though 'edit' is not allowed.

person Gnuffo1    schedule 20.04.2011    source источник


Ответы (1)


Похоже, вам нужно что-то вроде:

class WriteAssert implements Zend_Acl_Assert_Interface
{
    public function assert(Zend_Acl $acl,
                           Zend_Acl_Role_Interface $role = null,
                           Zend_Acl_Resource_Interface $resource = null,
                           $privilege = null)
    {
        // return whether the user owns the page
    }
}

$acl = new Zend_Acl;
$acl->addResource('page');
$acl->addRole('user');

$acl->allow('user', 'page', 'read');
$acl->allow('user', 'page', 'write', new WriteAssert);
$acl->isAllowed('user', 'page', 'write');

Здесь вы ожидаете, что пользователь сможет читать любую страницу, но писать только на свои собственные страницы.

person cmbuckley    schedule 20.04.2011
comment
Проблема в том, что я хочу, чтобы собственные правила страницы были другим ресурсом (потому что они будут храниться в базе данных и редактироваться из панели администратора). Поэтому, когда isAllowed () вызывается на странице, например, чтобы увидеть, разрешен ли доступ для записи, если пользователь владеет этой страницей, я хочу, чтобы ресурс собственной страницы был протестирован вместо просто страницы. Насколько я понимаю, это невозможно сделать с помощью утверждений. - person Gnuffo1; 20.04.2011