在我看来,ACL 并不是那么神奇。例如:ACL 可以管理权限以告知谁有权添加/编辑/删除产品.. 但它无法更改查询以根据定义的权限过滤产品(例如“来自 A 部门的用户只能查看 A 部门的产品").. 其实那是个谎言,ACL 可以管理它,但它可能不实用,因为每次添加产品时,您都必须创建一个 ACO,并在 AROS_ACOS 表中设置权限并且由于 AROS 是一个树结构,因此如果您打算查询数据,它很容易成为一个难题
我会使用仅限组的 ACL来控制对某些页面/操作的访问并制定如下规则:
- “部门负责人可以访问页面'产品列表'并添加/删除/修改产品”
- “管理员可以访问所有页面”
- “其他用户可以访问‘产品列表’,他们可以添加产品但不能删除它们”
我会根据连接的用户相应地调整我的查询,因此在“产品列表”页面的控制器中,我会执行以下操作:
- 如果连接的用户 blongs 到部门主管,则选择所有产品
product.department_id=connected_user.department_id
- 如果连接的用户是管理员,则选择所有产品
如果你有太多的查询并且你不想做成千上万的 if 语句,你可以创建一个组件、一个行为或者扩展find()
. app_model
这个想法是捕获所有查询并检查查询中使用的模型之一是否具有名为“department_id”的字段,如果有,则将model.department_id=connected_user.department_id
条件添加到查询中。
我为一个可以用多种语言查看的网站做到了这一点,每种语言都有自己的用户、数据、日志等,并且有一个管理员可以查看所有信息……这对我来说非常有用 =)
祝你好运!
编辑:
我使用的行为是:
<?php
class LocalizableBehavior extends ModelBehavior {
/**
* Filter query conditions with the correct `type' field condition.
*/
function beforeFind(&$model, $query)
{
/**
* Condition for the paginators that uses joins
*/
if(isset($query['joins']) && !empty($query['joins'])){
foreach($query['joins'] as $key => $joinTable){
if(ClassRegistry::init($joinTable['alias'])->hasField('lang')){
$query['joins'][$key]['conditions'][] = $joinTable['alias'].".lang = '".$_SESSION['lang']."'";
}
}
}
/**
* condition for the normal find queries
*/
if($model->hasField('lang') && $model->name != "User"){
$query['conditions'][$model->name.'.lang'] = $_SESSION['lang'];
}
return $query;
}
}
?>
这真的很简单,我更改查询以添加一个匹配当前语言的条件($_SESSION['lang'])。在控制器中,我需要做的就是附加 LocalizableBehavior 并像往常一样使用 find 方法:
$this->Products->find('all');