Этот вопрос возник при разработке специализированной системы ACL для пользовательского приложения, но я думаю, что она применима к системам ACL в целом, так как я не выяснил, как решить эту проблему, рассматривая некоторые из основных систем, как Zend_ACL
.
В моем приложении разрешения предоставляются динамически, например: пользователь получает разрешения на просмотр действия, потому что он является членом команды, с которой связано действие. Это основано на предположении, что у вас всегда есть Employee
(пользователь), который хочет выполнить действие (просмотр / редактирование / и т. Д.) Над Item
(одним из объектов в моем приложении, например Activity, Team и т. Д.) , Этого достаточно для моего целевого использования;
$Activity = new Activity( $_POST['activity_id'] );
$Acl = new Acl( $Activity );
if ( !$Acl->check( 'edit' ) {
throw new AclException('no permission to edit');
}
Мой Acl
класс содержит все бизнес-правила для предоставления разрешений, и они создаются «на лету» (хотя иногда и кэшируются по соображениям производительности);
/**
* Check the permissions on a given activity.
* @param Activity $Activity
* @param int $permission (optional) check for a specific permission
* @return mixed integer containing all the permissions, or a bool when $permission is set
*/
public function checkActivity( Activity $Activity, $permission = null ) {
$permissions = 0;
if ( $Activity->owner_actor_id == $this->Employee->employee_id ) {
$permissions |= $this->activity['view'];
$permissions |= $this->activity['remove'];
$permissions |= $this->activity['edit'];
} elseif ( in_array( $this->Employee->employee_id, $Activity->contributor_ids_arr ) ) {
$permissions |= $this->activity['view'];
} else {
/**
* Logged in user is not the owner of the activity, he can contribute
* if he's in the team the activity is linked to
*/
if ( $Activity->getTeam()->isMember( $this->Employee ) ) {
$permissions |= $this->activity['view'];
}
}
return ( $permission ? ( ( $permission & $permissions ) === $permission ) : $permissions );
}
Эта система работает как есть.
Проблема с этим подходом возникает, когда вы хотите «обратить» правила ACL. Например, «получить все действия, которые мне разрешено редактировать». Я не хочу помещать какую-либо логику, подобную WHERE owner_actor_id = $Employee->employee_id
, в код, который требует действий, потому что это ответственность класса Acl
, и она должна быть централизованной. В текущей реализации у меня нет другого варианта, чтобы получить все действия в коде, а затем утверждать их одну за другой. Это, конечно, очень неэффективный подход.
Итак, я ищу некоторые идеи хорошей архитектуры (или указатель на существующую реализацию ACL или некоторые соответствующие шаблоны проектирования) для создания системы ACL, которая может каким-то образом выполнять как hasPermission( $Item, $permission )
, так и fetchAllItems( $permission )
, в идеале с тем же набором бизнес-правил.
Спасибо всем заранее!
Я смотрел на реализацию Zend_ACL
, но она больше фокусируется на общих разрешениях. Я также нашел следующие вопросы здесь на SO:
Но, к сожалению, они, похоже, тоже не отвечают на вопрос.