我不确定我要回答的是否是最好的-最干燥-几乎是脱水的方法,但这是我能想到的最简单的方法。
在 Project 模型中,创建一个返回与用户关联的项目 ID 数组的函数。
class Project extends AppModel {
public function getByUserId($userId) {
$projectsArray = array();
if ($userId != "valid")
//do all the checks, if it's not null, numeric, if the id exists, etc
$projects = $this->Project->find('all', array('conditions'=>
array('user_id'=>$userId)));
if (!empty($projects)) {
foreach($projects as $i => $project)
$projectsArray[] = $project['Project']['id'];
}
return $projectsArray;
}
}
您在评论中提到了 a find('first')
,但我假设您想要与用户相关的所有项目,而不仅仅是第一个。如果不是,那只是对该函数的简单修改。另外,我只是在获取 ID,但您可能需要一个$id=>$name_project
数组,由您决定。
现在,我不知道您所说的“仅允许执行操作”是什么意思,是否只是限制编辑?或者如果项目不是他/她的,列表或视图应该受到限制,甚至不向用户显示?
对于第一种情况,限制编辑,修改beforeSave
.
public function beforeSave($options = array()) {
if(!$this->id && !isset($this->data[$this->alias][$this->primaryKey])) {
//INSERT
//not doing anything
} else {
//UPDATE
//check if project inside allowed projects array
$allowed = $this->getByUserId(CakeSession::read("Auth.User.id"));
if (!in_array($this->id, $allowed))
return false; //or throw error and catch it in the controller
}
return true;
}
该代码未经测试,但一般而言,您可以防止在更新记录之前编辑不是“用户”的项目。我假设每个人都可以免费插入新项目。根据这篇文章,除了首先通过此过滤器之外的所有保存功能saveAll
,因此您需要覆盖该saveAll
功能并添加类似于其中的验证beforeSave
(如那里的答案所述)。
而对于第二部分,过滤结果以便用户甚至不知道有其他项目而不是他/她的,change beforeFind
。文档讨论了根据用户角色限制结果,所以我想我们走在正确的轨道上。
public function beforeFind($queryData) {
//force the condition
$allowed = $this->getByUserId(CakeSession::read("Auth.User.id"));
$queryData['conditions'][$this->alias.'.user_id'] = $allowed;
return $queryData;
}
由于该$allowed
数组只有 id 值,它会像一个IN
子句一样工作,但如果您更改该数组结构,请务必相应地修改这些函数。
就是这样。我在这里考虑更基本的情况,编辑,查看,删除...... Ups,删除......beforeDelete
也改变功能,以避免任何想要删除其他财产的邪恶用户。逻辑保持不变(检查项目id是否在允许的数组中,如果不是,则返回false或抛出错误),因此我不会在此处添加该函数的示例。但这是基本的东西。如果出于某种原因您希望在控制器中拥有允许的项目,请调用该getByUserId
函数beforeFilter
并在那里处理该 ids 数组。您甚至可以将其存储在会话中,但您必须记住在添加或删除项目时维护该会话。
如果您想要一个可以查看和编辑所有内容的超级管理员,只需在其中添加一个getByUserId
检查用户角色的条件,如果是管理员,则返回所有项目。
另外,请记住:也许Project有很多...子项目(没有太多想象力),因此与该项目相关的用户可以添加子项目,但是与之前相同的邪恶用户修改了子项目具有的隐藏project_id并对其进行了编辑. 在这种情况下,我建议您还在子项目中添加一个验证,以避免对与项目相关的模型进行非他的操作。如果您有安全组件,并且编辑和删除操作只能通过表单进行,这是一件小事,因为安全组件使用得当可以避免表单篡改。但是请考虑一下您是否还需要验证“子项目”实例。
正如Ayo Akanyemi 所提到的,您可以将所有这些用作一种行为。我个人没有这样做,但是符合要求,这里修改的所有回调都是你在一个行为中修改的。您必须封装逻辑、列名(需要是变量而不是设置硬编码,例如user_id
)等,但它可以在您拥有的任何其他蛋糕项目中重复使用。像StrongBelongBehavior
或之类的东西MoreDRYBehavior
。如果你这样做,请分享它:)
我不确定 Auth 组件是否有某种方式可以做你想做的事,但我猜这将是最好的选择。直到有人启发我(我没有对这个问题进行太多调查),这就是我要使用的解决方案。