Yii2 RBAC check permissions without each actions in controller - php

How i can check permissions in one place?
I don't want to check each function individually.
My RBAC controller.
I would like check permission for logged in user for all actions in the controller. Now I have to use Yii::$app->user->can('...') individually for each actions in the controller
$admin = $auth->createRole('Admin');
$moderator = $auth->createRole('Moderator');
$createPost=$auth->createPermission('createPost');
$updatePost=$auth->createPermission('updatePost');
$deletePost=$auth->createPermission('deletePost');
$createCategory=$auth->createPermission('createCategory');
$updateCategory=$auth->createPermission('updateCategory');
$deleteCategory=$auth->createPermission('deleteCategory');
$auth->add($admin);
$auth->add($moderator);
$auth->add($createPost);
$auth->add($updatePost);
$auth->add($deletePost);
$auth->add($createCategory);
$auth->add($updateCategory);
$auth->add($deleteCategory);
Here I assign role with permissions, but i never use these permissions because write manually in behavior->(like your example)
What is goal, create permissons in RBAC, if this not working? If I would like add premium user. I could only add action in controller e.g. actionPremium and set in behavior actions for premium user.
e.g
action=>['premium']
roles=>['premiumUser']
and one more question.
How in behavior customize message error?
$auth->addChild($admin,$moderator);
$auth->addChild($admin,$createCategory);
$auth->addChild($admin,$updateCategory);
$auth->addChild($admin,$deleteCategory);
$auth->addChild($moderator, $createPost);
$auth->addChild($moderator, $updatePost);
$auth->addChild($moderator, $deletePost);
$auth->assign($admin,1);
$auth->assign($moderator,2);

You can assign the permission allowed in controller for all action in behaviors
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['index','view'], // these action are accessible
//only the yourRole1 and yourRole2
'allow' => true,
'roles' => ['yourRole1', 'yourRole2'],
],
[ // all the action are accessible to superadmin, admin and manager
'allow' => true,
'roles' => ['superAdmin', 'admin', 'manager'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post'],
],
],
];
}
The role you assigned in behaviors are for action .. allowd or deny .. the if a role had an allowed action in behaviors then he can execute otherwise he get permission denied 403 .. (not authorized) ..
You can also check the role in procedural code with
if ( Yii::$app->User->can('admin') ){
.....
yourdCode
....
}

Related

Yii2 REST API as Module route configuration

I have an existing Yii2 application and have been trying to implement a REST API as an additional module (Maybe a module isn't the correct way to go about this?) But I'm having some trouble configuring the route structures. It doesn't quite work and doesn't follow the expected results, based of the following guide.
I've built an additional module that looks like this:
module
api
controllers
UserController.php
Module.php
UserController.php
<?php
namespace app\modules\api\controllers;
use yii\rest\ActiveController;
class UserController extends ActiveController
{
public $modelClass = 'app\models\User';
}
Module.php
<?php
namespace app\modules\api;
/**
* onco module definition class
*/
class Module extends \yii\base\Module
{
public $defaultController = 'user';
/**
* #inheritdoc
*/
public $controllerNamespace = 'app\modules\api\controllers';
/**
* #inheritdoc
*/
public function init()
{
parent::init();
// custom initialization code goes here
}
}
In my config file I have the added following:
'request' => [
...
'parsers' => [
'application/json' => 'yii\web\JsonParser',
]
],
...
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => false, // have tried as true also
'rules' => [
...
['class' => 'yii\rest\UrlRule', 'controller' => '\app\modules\api\controllers\user'],
],
],
...
'modules' => [
...
'api' => [ // module for RESTful API
'class' => 'app\modules\api\Module',
],
]
When I run the following urls through postman I get the following:
http://localhost/site1/web/api/users -> 404
http://localhost/site1/web/api/users/index -> 404
http://localhost/site1/web/api/user/index -> returns json repsonse
http://localhost/site1/web/api/user/2 -> 404
I'm unsure as to why the predicted routes of noted in the docs as:
Trying it Out With the above minimal amount of effort, you have
already finished your task of creating the RESTful APIs for accessing
the user data. The APIs you have created include:
GET /users: list all users page by page;
HEAD /users: show the overview information of user listing;
POST /users: create a new user;
GET /users/123: return the details of the user 123;
HEAD /users/123: show the overview information of user 123;
PATCH /users/123 and PUT /users/123: update the user 123;
DELETE /users/123: delete the user 123;
OPTIONS /users: show the supported verbs regarding endpoint /users;
OPTIONS /users/123: show the supported verbs regarding endpoint /users/123
What have I likely done wrong in this setup? Is there a better way to implement an API into an existing website, whilst maintaining DRY practices?
try this:
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => ['api/user'],
]
]
],
...
'modules' => [
...
'api' => [
'basePath' => '#app/modules/api',
'class' => 'app\modules\api\Module',
],
]
Also be sure to implement prettyUrl's related server server configs.

Multiple Login table in yii2 IdentityInterface error while login

I have 2 different tables user and organiser and i am trying to create 2 different login for both users.
I am able to sign them up easily and get the record in database but after saving the record i get the error on following code line
if ($user = $model->signup()) {
if (Yii::$app->getUser()->login($user)) { //yii\web\IdentityInterface error
return $this->goHome();
}
}
Following is my configuration module
'components' => [
'user' => [
'identityClass' => 'common\models\User',
'enableAutoLogin' => true,
'identityCookie' => [
'name' => '_frontendOrganiser', // unique for frontend
],
],
'users' => [
'class' => 'yii\web\User',
'identityClass' => 'common\models\Users',
'enableAutoLogin' => false,
'enableSession' => true,
'identityCookie' => [
'name' => '_frontendUser', // unique for frontend
],
],
'session' => [
'name' => 'PHPFRONTSESSID',
'savePath' => sys_get_temp_dir(),
],
]
So what is wrong am i doing here? Do i need to create any other Interface or something or provide different interface for different module?
And i had to do this because organiser table uses password_hash technique to log in the users where my user table is from another project and they uses md5 technique, so i had to create separate module for both users.
Argument 1 passed to yii\web\User::login() must be an instance of yii\web\IdentityInterface, instance of common\models\Users given, called in C:\xampp\htdocs\project\frontend\controllers\SiteController.php on line 202 and defined
The exact error statement is as above.
I think your user model don't implement the Identity interface correctly.
Try check you data model also (in your DB) this must contain all the field managed bay the interface.
And be sure you User implement the Identity Interface correctly.
and mapping the interface method with your model correctly..
See the interface doc for this http://www.yiiframework.com/doc-2.0/yii-web-identityinterface.html

How to access defined URL in Yii2

I have controller UserController and action actionAjax. I access by Chrome with below URL and it is working normally.
index.php?r=user/ajax
Now I define new action with named actionAjaxUser, still using Chrome to access URL index.php?user/ajaxUser
Then 404 returned.
What should I do to getting content of actionAjaxUser?
add for each additional uppercase Letter after "action" a "-" so in your case
index.php?r=user/ajax-user
So if you would have an action like actionTest1Test2Test3 the url would be controllername/test1-test2-test3.
Be aware that if you are using access rules you also have to use the "url" path.
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['test1-test2-test3'],
'allow' => true,
'roles' => ['#'],
],
],
],
];
The same Naming scheme is btw. also used for Controllers. E.g. if your Controller is named Test1Test2Controller the view folder name would be test1-test2.
Hope this clarifies this for you.

Override Yii2 assetManager config in controller

I use yii-jui to add some UI elements in the views such as datePicker. In the frontend\config\main-local.php I set the following to change the theme used by the JqueryUI:
$config = [
'components' => [
'request' => [
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => 'gjhgjhghjg87hjh8878878',
],
'assetManager' => [
'bundles' => [
'yii\jui\JuiAsset' => [
'css' =>
['themes/flick/jquery-ui.css'],
],
],
],
],
];
I tried the following to override this configuration item in the controller actions method:
public function actions() {
Yii::$app->components['assetManager'] = [
'bundles' => [
'yii\jui\JuiAsset' => [
'css' =>
['themes/dot-luv/jquery-ui.css'],
],
],
];
return parent::actions();
}
Also I tried to set the value of Yii::$app->components['assetManager'] shown above to the view itself (it is partial view of form _form.php) and to the action that calls this view (updateAction). However, all this trying doesn't be succeeded to change the theme. Is there in Yii2 a method like that found in CakePHP such as Configure::write($key, $value);?
You should modify Yii::$app->assetManager->bundles (Yii::$app->assetManager is an object, not an array), e.g.
Yii::$app->assetManager->bundles = [
'yii\jui\JuiAsset' => [
'css' => ['themes/dot-luv/jquery-ui.css'],
],
];
Or if you want to keep other bundles config :
Yii::$app->assetManager->bundles['yii\jui\JuiAsset'] = [
'css' => ['themes/dot-luv/jquery-ui.css'],
];
You are going about this all wrong, you want to change the JUI theme for 1 controller alone because of a few controls. You are applying 2 css files to different parts of the website that have the potential to change styles in the layouts too. The solution you found works but it is incredibly bad practice.
If you want to change just some controls do it the proper way by using JUI scopes.
Here are some links that will help you:
http://www.filamentgroup.com/lab/using-multiple-jquery-ui-themes-on-a-single-page.html
http://jqueryui.com/download/
In this way you are making the website easier to maintain and you do not create a bigger problem for the future than you what solve.

yii2.0 gives 403 error while running http://localhost/~name/yii2hello/backend/web/index.php?r=site/say

I'm new to yii. With much difficulty i set up yii2.0 advanced and tried to run the simple hello program.
I added the following code in backend/Controllers/SiteController.php
public function actionSay($message = 'Hello')
{
return $this->render('say',['message' => $message]);
}
Then, I created say.php file in backend/views/site/ with the following code
<?php
use yii\helpers\Html;
?>
<?= Html::encode($message) ?>
I typed ../yii2hello/backend/web/index.php?r=site/say&message=Hello+World in browser to access the page.
I got the 403 error "you are not allowed to perform this action."
Can anyone tell me where is the problem ?
This error happens when you don't define permissions to access this action.
You have to add the permission to your action like the following:
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['say'],
'allow' => true,
],
],
]
];
}

Categories