我正在制作一个应用程序,用户可以在其中创建活动,其他用户可以订阅活动。新活动必须通过管理面板批准,只有管理员才能访问。
已批准的活动应被锁定,以使用户无法更改。只有通过管理面板批准的活动才可以编辑。
要实现这一点,我们制作了buildRule:
public function buildRules(RulesChecker $rules)
{
// Check if activity wasn't locked
$rules->add(function ($entity, $settings)
{
// Return false if already approved before
return !$entity->approved || $entity->isDirty('approved');
}, 'alreadySubscribed', ['errorField' => 'name', 'message' => 'Activity has been approved and is now locked']);
return $rules;
}
(BuildRule而不是验证规则,因为在未修改approved
字段时验证也应加入,因此不属于验证范围。)
上面给出的规则也阻止管理员修改活动,所以我的问题:
您可以在表中的builRules之间切换,就像可以更改验证方法吗?
答案 0 :(得分:1)
并非如此,有一个Model.buildRules
事件可用于添加规则,仅此而已。
我不确定根据模型外部的状态来微调多个应用程序规则是否是一个好主意。您想要达到的目标听起来像访问控制,即授权,我建议相应地执行检查。
看看 cakephp/authorization ,它使您可以实施非常灵活的策略来处理此类情况。另外,还有auth组件提供的旧式授权功能,或者(高度未记录的) ACL 插件。
如果您的授权确实非常基础,即“ 管理区域=允许编辑”和“ 非管理区域=不允许编辑”,即可能只是在应用程序中需要检查的这一点上,那么您可能会摆脱一些不太复杂的事情,例如将选项传递到保存过程中。这些选项将传递到规则中,您可以在其中进行相应的检查,例如:
$options = [
'updateApproved' => true
];
$Model->save($entity, $options);
function ($entity, $settings)
{
if (isset($settings['updateApproved']) &&
$settings['updateApproved'] === true
) {
return true;
}
// ...
return !$entity->approved || $entity->isDirty('approved');
}
只有通过true
选项传递updateApproved
时,保存批准的实体才有效。如前所述,这并不是一个很好的解决方案,无论如何,我建议您看看 authorzation plugin 并学习如何正确实施授权。
另请参见
答案 1 :(得分:0)
我想@ndm的解决方案是更正式的解决方案。我最终得到了一个不同的解决方案,我想先尝试一下。
基本上,我向“活动”模型添加了一个标记:
class ActivitiesTable extends Table
{
/** @var bool Flag whether admin is modifying the table */
private $_admin = false;
// ...
并使构建的规则依赖于此:
if (!$this->_admin)
{
$rules->add(function ($entity, $settings)
{
// ...
然后,您可以在控制器中将模型切换为管理模式,并保存否则将失败的实体:
$this->Activities->_admin = true;
$this->Activities->save($activity);