简体   繁体   English

只允许作者使用ACF在yii2中编辑他的帖子

[英]Allow only author to edit his post in yii2 using ACF

I am using Access Control Filter for access managing, but can't get one thing done - for example, how can I allow just project manager to update project and forbid it to others? 我使用访问控制过滤器进行访问管理,但无法完成一件事 - 例如,我如何才能让项目经理更新项目并禁止其他人? I tried it via matchCallback, but in this case all project managers can update any project because TRUE is returned. 我通过matchCallback尝试了它,但在这种情况下,所有项目经理都可以更新任何项目,因为返回了TRUE。

Similar more often required rules - how to allow user to update/delete posts where he is author using ACF? 类似的更常用的规则 - 如何允许用户使用ACF更新/删除他是作者的帖子?

         'access' => [
            'class' => AccessControl::className(),
            'only' => ['index', 'view', 'create', 'update', 'delete'],
            'rules' => [
                [
                    'actions' => ['update'],
                    'allow' => true,
                    'roles' => ['@'],
                    'matchCallback' => function ($rule, $action) {

                        return Yii::$app->user->identity->getProjectParticipants()
                                    ->one()->isManager(Yii::$app->user->identity->id);
                    }
                ],
            ],
        ],

It could be implemented something like this: 它可以实现如下:

use Yii;
use yii\web\Controller;
use yii\filters\AccessControl;

class MyController extends Controller
{

...

    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'only' => ['update', 'delete'],
                'rules' => [
                    [
                        'actions' => ['update', 'delete'],
                        'allow' => true,
                        'roles' => ['@'],
                        'matchCallback' => function ($rule, $action) {
                            if (Yii::$app->user->can('admin') || $this->isUserAuthor()) {
                                return true;
                            }
                            return false;
                        }
                    ],
                ],
            ],
        ];
    }

    protected function findModel($id)
    {
        if (($model = MyModel::findOne($id)) !== null) {
            return $model;
        } else {
            throw new NotFoundHttpException('The requested page does not exist.');
        }
    }

    protected function isUserAuthor()
    {   
        return $this->findModel(Yii::$app->request->get('id'))->author->id == Yii::$app->user->id;
    }

...

}

This is bested solved with a custom AccessRule . 这是通过自定义AccessRule解决的问题。 One would have to fill in the code to check if a user is the author of a project. 必须填写代码以检查用户是否是项目的作者。

namespace app\filters;

class AuthorAccessRule extends \yii\filters\AccessRule
{
    public $allow = true;  // Allow access if this rule matches
    public $roles = ['@']; // Ensure user is logged in.

    public function allows($action, $user, $request)
    {
        $parentRes = parent::allows($action, $user, $request);
        // $parentRes can be `null`, `false` or `true`.
        // True means the parent rule matched and allows access.
        if ($parentRes !== true) {
            return $parentRes;
        }
        return ($this->getProjectAuthorId($request) == $user->id);
     }

     private function getProjectAuthorId($request)
     {
         // Fill in code to receive the right project.
         // assuming the project id is given à la `project/update?id=1`
         $projectId = $request->get('id');
         $project = \app\models\Project::findOne($projectId);
         return isset($project) ? $project->author_id : null;
     }
}

The rule can be used by including this in the behaviors: 可以通过在行为中包含此规则来使用该规则:

'authorAccess' => [
        'class' => AccessControl::className(),
        'only' => ['update'],
        'rules' => ['actions' => ['update']],
        'ruleConfig' => ['class' => '\app\filters\AuthorAccessRule'],
],

Following is how I do it with combination of ACF and RBAC. 以下是我如何使用ACF和RBAC的组合。 Please correct me if I am wrong or there is better way of doing it. 如果我错了或者有更好的方法,请纠正我。 It's based on Basic template. 它基于Basic模板。

  1. User's role is stored in the "role" column of the "user" table. 用户角色存储在“用户”表的“角色”列中。 Another table "country" is used in this example. 在此示例中使用另一个表“country”。 Assume you have generated models and controllers using Gii. 假设您已使用Gii生成模型和控制器。

  2. Customise PhpManager to use role from database table "user". 自定义PhpManager以使用数据库表“user”中的角色。

class PhpManager extends \yii\rbac\PhpManager
{
    public function init()
    {
        parent::init();
    }

    public function getAssignments($userId)
    {
        if (!Yii::$app->user->isGuest) {
            $assignment = new Assignment();
            $assignment->userId = $userId;
            # Assume the role is stored in User table "role" column
            $assignment->roleName = Yii::$app->user->identity->role;
            return [$assignment->roleName => $assignment];
        }
    }
}

3. Add authManager to web.app and console.app console file. 3.将authManager添加到web.app和console.app控制台文件。

    'authManager' => [
        'class' => 'app\components\PhpManager',
        'defaultRoles' => ['user', 'manager', 'admin', 'master'],
    ],
  1. Create a customized AccessRule. 创建自定义的AccessRule。 Reference from speixoto's blog . 来自speixoto博客的参考资料。

 # Reference # http://programming.peixoto.cf/2015/01/14/yii2-role-based-access-control-and-context-access-rule/#$$nmvkr0&&0SUmhOPVEeSW9grIhAgzZg$$ class ContextAccessRule extends AccessRule { public $modelClass; public $primaryKey; protected function matchRole($user) { if (parent::matchRole($user)) return true; $model = $this->findModel(); foreach ($this->roles as $role) { # Call the CheckAccess() function which process rules if ($user->can($role, ['model' => $model])) { return true; } } return false; } protected function findModel() { if (!isset($this->modelClass)) throw new InvalidConfigException(Yii::t('app', 'the "modelClass" must be set for "{class}".', ['class' => __CLASS__])); $primaryKey = $this->getPrimaryKey(); # Get the request params $queryParams = \\Yii::$app->getRequest()->getQueryParams(); # Load the model $model = call_user_func([$this->modelClass, 'findOne'], $queryParams[join(',', $primaryKey)]); if ($model !== null) { return $model; } else { throw new NotFoundHttpException(Yii::t('app', 'The requested page does not exists.')); } } # Get the primary key of the model protected function getPrimaryKey() { if (!isset($this->primaryKey)) { return call_user_func([$this->modelClass, 'primaryKey']); } else { return $this->primaryKey; } } 

  1. Create a RbacController.php to generate RBAC files (assignments.php, items.php, rules.php) into rbac folder. 创建一个RbacController.php以生成RBAC文件(assignments.php,items.php,rules.php)到rbac文件夹中。

 class RbacController extends Controller { public function actionInit() { $auth = Yii::$app->authManager; $auth->removeAll(); ### CREATE & ADD ROLES $user = $auth->createRole('user'); $node = $auth->createRole('node'); $manager = $auth->createRole('manager'); $admin = $auth->createRole('admin'); $master = $auth->createRole('master'); $auth->add($user); $auth->add($node); $auth->add($manager); $auth->add($admin); $auth->add($master); $auth->addChild($manager, $user); $auth->addChild($manager, $node); $auth->addChild($admin, $manager); $auth->addChild($master, $admin); ### ADD RULES $ownerRule = new \\app\\components\\OwnerRule(); $auth->add($ownerRule); ### CREATE PERMISSIONS ### $pUpdateOwn = $auth->createPermission('updateOwn'); $pUpdateOwn->description = 'update own'; $pUpdateOwn->ruleName = $ownerRule->name; $auth->add($pUpdateOwn); $auth->addChild($pUpdateOwn, $pUpdate); $pDeleteOwn = $auth->createPermission('deleteOwn'); $pDeleteOwn->description = 'delete own'; $pDeleteOwn->ruleName = $ownerRule->name; $auth->add($pDeleteOwn); $auth->addChild($pDeleteOwn, $pDelete); ### ASSIGN PERMISSION TO ROLES $auth->addChild($user, $pUpdateOwn); $auth->addChild($user, $pDeleteOwn); $auth->addChild($manager, $pUpdateOwn); $auth->addChild($manager, $pDeleteOwn); } } 

  1. From console, navigate to your project root. 从控制台,导航到项目根目录。 Run ./yii rbac/init (for mac) to generate the 3 files into rbac folder. 运行./yii rbac/init (对于mac)将3个文件生成到rbac文件夹中。

  2. In CountryController.php, override following function to add "access" behaviors. 在CountryController.php中,覆盖以下函数以添加“访问”行为。

  public function behaviors() { $behaviors = parent::behaviors(); $behaviors['verbs'] = [ 'class' => VerbFilter::className(), 'actions' => [ 'delete' => ['post'], ], ]; ['access'] = [ 'class' => AccessControl::className(), // 'only' => ['view', 'index', 'create', 'update', 'delete'], 'rules' => [ [ 'actions' => ['view', 'index'], 'allow' => true, 'roles' => ['?', '@'], ], [ 'actions' => ['create'], 'allow' => true, // Allow users, manager and admins to create 'roles' => ['user'], ], [ 'class' => 'app\\components\\ContextAccessRule', 'modelClass' => 'app\\models\\Country', 'actions' => ['update'], 'allow' => true, # allow owner and manager to udpate 'roles' => ['updateOwn', 'manager'] ], [ 'class' => 'app\\components\\ContextAccessRule', 'modelClass' => 'app\\models\\Country', 'actions' => ['delete'], 'allow' => true, # allow owner and manager to delete 'roles' => ['deleteOwn', 'manager'], ], ], # if user not login, and not allowed for current action, return following exception 'denyCallback' => function ($rule, $action) { throw new UnauthorizedHttpException('You are not authorized.'); }, ]; return $behaviors; } 
8. Test it out. 8.测试一下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM