Php 仅允许作者使用ACF在yii2中编辑其帖子

Php 仅允许作者使用ACF在yii2中编辑其帖子,php,yii2,access-control,role,yii2-user,Php,Yii2,Access Control,Role,Yii2 User,我正在使用访问控制过滤器进行访问管理,但无法完成一件事——例如,我如何才能只允许项目经理更新项目并禁止其他人使用它?我通过matchCallback进行了尝试,但在本例中,所有项目经理都可以更新任何项目,因为返回TRUE 类似的更经常需要的规则-如何允许用户更新/删除使用ACF编写的帖子 'access' => [ 'class' => AccessControl::className(), 'only' =>

我正在使用访问控制过滤器进行访问管理,但无法完成一件事——例如,我如何才能只允许项目经理更新项目并禁止其他人使用它?我通过matchCallback进行了尝试,但在本例中,所有项目经理都可以更新任何项目,因为返回TRUE

类似的更经常需要的规则-如何允许用户更新/删除使用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);
                    }
                ],
            ],
        ],

下面是我如何结合ACF和RBAC来实现它的。如果我错了或者有更好的方法,请纠正我。它基于基本模板

  • 用户的角色存储在“用户”表的“角色”列中。本例中使用了另一个表“国家”。假设您已经使用Gii生成了模型和控制器

  • 自定义PhpManager以使用数据库表“user”中的角色

  • 类PhpManager扩展\yii\rbac\PhpManager
    {
    公共函数init()
    {
    父::init();
    }
    公共函数getAssignments($userId)
    {
    如果(!Yii::$app->user->isGuest){
    $assignment=新分配();
    $assignment->userId=$userId;
    #假设角色存储在用户表“角色”列中
    $assignment->roleName=Yii::$app->user->identity->role;
    返回[$assignment->roleName=>$assignment];
    }
    }
    }
    
    3.将authManager添加到web.app和console.app控制台文件。

  • 创建自定义的AccessRule。引用自
  • #参考
    # http://programming.peixoto.cf/2015/01/14/yii2-role-based-access-control-and-context-access-rule/#$$nmvkr0&&0SUmhOPVEeSW9grIhAgzZg$$
    类ContextAccessRule扩展了AccessRule
    {
    公共模型类;
    公共$primaryKey;
    受保护的函数匹配角色($user)
    {
    if(父::匹配角色($user))
    返回true;
    $model=$this->findModel();
    foreach($this->roles as$role){
    #调用处理规则的CheckAccess()函数
    如果($user->can($role,['model'=>$model])){
    返回true;
    }
    }
    返回false;
    }
    受保护函数findModel()
    {
    如果(!isset($this->modelClass))
    抛出新的InvalidConfigException(Yii::t('app','modelClass'必须为“{class}”设置,['class'=>\uuuuu class]);
    $primaryKey=$this->getPrimaryKey();
    #获取请求参数
    $queryParams=\Yii::$app->getRequest()->getQueryParams();
    #加载模型
    $model=call_user_func([$this->modelClass,'findOne',$queryParams[join(',',$primaryKey)];
    如果($model!==null){
    返回$model;
    }否则{
    抛出新的NotFoundHttpException(Yii::t('app','请求的页面不存在');
    }
    }
    #获取模型的主键
    受保护的函数getPrimaryKey()
    {
    如果(!isset($this->primaryKey)){
    返回调用用户函数([$this->modelClass,'primaryKey']);
    }否则{
    返回$this->primaryKey;
    }
    
    }
    这最好用自定义的
    AccessRule
    来解决。必须填写代码以检查用户是否是项目的作者

    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;
         }
    }
    
    该规则可通过在行为中包含以下内容来使用:

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

    它可以这样实现:

    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;
        }
    
    ...
    
    }
    

    你找到解决办法了吗?
    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;
        }
    
    ...
    
    }