Allow only author to edit his post in yii2 using ACF

I use the Access Control Filter to control access, but I canโ€™t do anything - for example, how can I allow only the project manager to update the project and prevent it from others? I tried this through matchCallback, but in this case, all project managers can update any project because TRUE is returned.

The most often required similar rules are: how to allow the user to update / delete messages where he is the author using 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); } ], ], ], 
+6
source share
3 answers

It can 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; } ... } 
+4
source

This is fixed using a custom AccessRule . You need to fill in the code to check if the user is the author of the 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; } } 

This rule can be used by including it in the behavior:

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

Here's how I do it with a combination of ACF and RBAC. Please correct me if I am wrong, or is there a better way to do this. It is based on a basic template.

  • The user role is stored in the "role" column of the "user" table. This example uses a different country table. Suppose you created models and controllers using Gii.

  • Configure PhpManager to use the role from the "user" database table.

 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 the authManager file to the web.app and console.app file.

  'authManager' => [ 'class' => 'app\components\PhpManager', 'defaultRoles' => ['user', 'manager', 'admin', 'master'], ], 
  1. Create a custom AccessRule. Link from speixoto blog .

 # 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 RbacController.php to create RBAC files (assignments.php, items.php, rules.php) in the rbac folder.

 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 the console, go to the root of the project. Run ./yii rbac/init (for mac) to generate 3 files in the rbac folder.

  2. In CountryController.php, override the following function to add "access" behavior.

  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. Check it out.
+1
source

Source: https://habr.com/ru/post/984206/


All Articles