I couldnt post sooner coz i had to waith for 12 hours after i signed up to post more than 2 posts. Anyway I managed to get around the problem but now i cant access the uploads page at all. it throws a #403 forbidden error.
Here is my rbac controller file which creates permissions and roles assigns users to roles. I have some users with id 12-15.
<?php
namespace console\controllers;
use Yii;
use yii\console\Controller;
class RbacController extends Controller
{
public function actionInit()
{
$auth = Yii::$app->authManager;
//index permission
$index=$auth->createPermission ('uploads/index');
$index->description='View Upload index';
$auth->add($index);
//add "createUpload" permission
$create=$auth->createPermission ('uploads/create');
$create->description='Create Upload';
$auth->add($create);
//add "updateUpload" permission
$update=$auth->createPermission ('uploads/update');
$update->description='Update Upload';
$auth->add($update);
//add deleteUpload permission
$delete=$auth->createPermission ('uploads/delete');
$delete->description='Delete Upload';
$auth->add($delete);
//add "viewUpload" permission
$view=$auth->createPermission ('uploads/view');
$view->description='view Upload';
$auth->add($view);
// add "client" role and give this role the "create,index,view" permission
$client = $auth->createRole('client');
$auth->add($client);
$auth->addChild($client, $index);
$auth->addChild($client, $create);
$auth->addChild($client, $view);
//add admin role and give them delete and update permissions as well as clients permissions
$admin = $auth->createRole('admin');
$auth->add($admin);
$auth->addChild($admin, $client);
$auth->addChild($admin, $delete);
$auth->addChild($admin, $update);
//assign roles
$auth->assign($admin,12);
$auth->assign($client,13);
$auth->assign($client,14);
$auth->assign($client,15);
// add the rule
$rule = new \console\rbac\ClientRule;
$auth->add($rule);
// add the "$updateOwnUpload" permission and associate the rule with it.
$updateOwnUpload = $auth->createPermission('updateOwnUpload');
$updateOwnUpload->description = 'Update own upload';
$updateOwnUpload->ruleName = $rule->name;
$auth->add($updateOwnUpload);
//$update=$auth->createPermission('auth/post/update');
// "updateOwnUpload" will be used from "updatePost"
$auth->addChild($updateOwnUpload, $update);
// allow "clients" to update their own posts
$auth->addChild($client, $updateOwnUpload);
}
}
here is my uploads controller
<?php
namespace frontend\controllers;
use Yii;
use frontend\models\Uploads;
use frontend\models\UploadsSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\web\UploadedFile;
use yii\filters\AccessControl;
/**
* UploadsController implements the CRUD actions for Uploads model.
*/
class UploadsController extends Controller
{
/*
public function behaviors()
{
return[
'verbs'=>[
'class'=>VerbFilter::className(),
'actions'=>[
'delete'=>['post'],
],
],
];
*/
public function behaviors()
{
$behaviors ['access']= [
'class'=>AccessControl::className(),
'rules'=>[
[
'allow'=>true,
'roles'=>['@'],
'matchCallback'=>function ($rule, $action) {
$module =Yii::$app->controller->module->id;
$action =Yii::$app->controller->action->id;
$controller=Yii::$app->controller->id;
$route="$controller/$action";
$post =Yii::$app->request->post();
if(\Yii::$app->user->can($route)){
return true;
}
}
],
],
];
return $behaviors;
}
/**
* Lists all Uploads models.
* @return mixed
*/
public function actionIndex()
{
$searchModel = new UploadsSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Uploads model.
* @param integer $id
* @return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Uploads model.
* If creation is successful, the browser will be redirected to the 'view' page.
* @return mixed
*/
public function actionCreate()
{
$model = new Uploads();
if ($model->load(Yii::$app->request->post()))
{
$model->user_id = Yii::$app->user->getId();
//get file instance
$imageName=$model->upload_name;
$model->file= UploadedFile::getInstance($model,'file');
$model->file->saveAs('uploads/'.$imageName.'.'.$model->file->extension);
//save path in db column
$model->upload_path='uploads/'.$imageName.'.'.$model->file->extension;
$model->upload_date=date('Y-m-d h:m:s');
$model->save();
return $this->redirect(['view', 'id' => $model->upload_id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
/**
* Updates an existing Uploads model.
* If update is successful, the browser will be redirected to the 'view' page.
* @param integer $id
* @return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post())
&& $model->save()) {
return $this->redirect(['view', 'id' => $model->upload_id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing Uploads model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* @param integer $id
* @return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the Uploads model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* @param integer $id
* @return Uploads the loaded model
* @throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Uploads::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
here is my access rule file
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
namespace console\rbac;
class ClientsAccessRule 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->getUser_id($request) == $user->id);
}
public function getUser_id($request)
{
// Fill in code to receive the right project.
// assuming the project id is given à la `project/update?id=1`
$upload_id = $request->get('id');
$uploads = frontend\models\Uploads::findOne($upload_id);
return isset($uploads) ? $uploads->user_id : null;
}
}
and finally here is my rule file
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
namespace console\rbac;
use yii\rbac\Rule;
/**
* Checks if authorID matches user passed via params
*/
class ClientRule extends Rule
{
public $name = 'isClient';
/**
* @param string|integer $user the user ID.
* @param Item $item the role or permission that this rule is associated with
* @param array $params parameters passed to ManagerInterface::checkAccess().
* @return boolean a value indicating whether the rule permits the role or permission it is associated with.
*/
public function execute($user, $item, $params)
{
if(isset($params['model'])){ //Directly specify the model you plan to use via param
$model=$params['model'];
}else {//use the controller findModel method to get the model-this is what executes via the behavior rule
$id=\Yii::$app->request->get('id'); //note this is an assumption on you url structure
$model=\Yii::$app->controller->findUserModel($id); //note this only works if you change findModel to be public
}
return $model->user_id==$user;
}
}