0

我正在制作一个应用程序,用户可以在其中创建活动,其他用户可以订阅它们。新活动必须通过管理面板批准,只有管理员可以访问。

被批准的活动应该被锁定,这样他们的用户就不能改变它们。只有通过管理面板批准的活动才能进行编辑。

为了实现这一点,我们制作了这个 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 之间切换,就像您可以更改验证方法一样?

4

2 回答 2

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选项传递时才能保存已批准的实体。如前所述,这并不是一个非常好的解决方案,无论如何我建议查看授权插件并学习如何正确实施授权。

也可以看看

于 2018-10-19T15:35:34.870 回答
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);
于 2018-10-21T15:04:05.000 回答