charlesportwoodii / yii2-api

A Yii2 API Skeleton Framework
BSD 3-Clause "New" or "Revised" License
11 stars 1 forks source link

Suggestions for Implementing editOwnModel permission #3

Closed dbd5 closed 1 month ago

dbd5 commented 3 years ago

Hello,

I am trying to base an API project on this framework and the related components project.

My project makes extensive use of the editOwnModel permission.

Considering how yrc\rest\Controller implements the filters acl (works great, thanks) and that the model is unknown at this point - meaning all calls to ->can('editOwnModel') will fail, what is the best way to limit access using the editOwnModel permission?

Thanks in advance!

charlesportwoodii commented 3 years ago

I'm not familiar with editOwnModel. It's not a standard Yii2 filter. Can you link to what you're referencing in the Yii2 documentation? Is this a custom filter you're looking to add?

dbd5 commented 3 years ago

My apologies for causing the confusion.

editOwnModel is a custom business rule in my code but is modelled like what the documentation calls updateOwnPost here https://www.yiiframework.com/doc/guide/2.0/en/security-authorization

Like all rules, OwnModelRule or updateOwnPost extends yii\rbac\Rule. In particular, a model and an attribute like 'created_by' can be passed and compared with the active user to determine if the user is the one that created or otherwise owns the model.

In a regular controller as in the example below, Yii::$app->user->can('editOwnModel', ...) evaluates the permission using the model and attribute parameters passed in the callback when the rule is evaluated. Its easy to conjur the model in the controller Init(), but I haven't figured out a way to do something similar for the acl in your API kit. Thanks

public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'rules' => [
                    [
                        'actions' => [
                            'view',
                        ],
                        'allow' => true,
                        'roles' => ['@'],
                        'matchCallback' => function () {
                            return Yii::$app->user->can('editOwnModel', [
                                'model' => $this->model,
                                'attribute' => 'created_by',
                            ]);
                        },
                    ],
                ],
            ],
        ];
    }
dbd5 commented 3 years ago

This is the execute method of the rule;

public function execute($user, $item, $params)
    {
        if (!isset($params['model'])) {
            return false;
        }

        $attribute = isset($params['attribute']) ? $params['attribute'] : 'created_by';
        $result = ($user && isset($params['model']) && $user === $params['model']->getAttribute($attribute));

        return $result;
    }
charlesportwoodii commented 3 years ago

Perhaps I'm misunderstanding what you're trying to achieve, but you can always override, overload, or extend the behaviors method to attach any custom behavior or filter you're looking for - there's nothing in place that restricts what for your controllers.

    public function behaviors()
    {
        $behaviors = parent::behaviors();

        $behaviors['access']['rules'][] = [
            // Add any additional rules here....
        ];

        return $behaviors;
    }

Yii2's sample starter kit has it's own OwnModel filter you could also probably drop in to achieve what you're doing as well: https://github.com/yii2-starter-kit/yii2-starter-kit/blob/master/common/filters/OwnModelAccessFilter.php.

dbd5 commented 3 years ago

Thank you.

I will take a closer look and revert