RBAC in Yii2 with PhpManager - yii2

How can I implement RBAC in Yii 2.0 without any database.
I will have just 2 roles , i.e. admin and author .
my RbacController is
<?php
namespace app\commands;
use Yii;
use yii\console\Controller;
class RbacController extends Controller
{
public function actionInit()
{
$auth = \Yii::$app->authManager;
// add "createPost" permission
$createPost = $auth->createPermission('createPost');
$createPost->description = 'Create a post';
$auth->add($createPost);
// add "updatePost" permission
$updatePost = $auth->createPermission('updatePost');
$updatePost->description = 'Update post';
$auth->add($updatePost);
// add "author" role and give this role the "createPost" permission
$author = $auth->createRole('author');
$auth->add($author);
$auth->addChild($author, $createPost);
// add "admin" role and give this role the "updatePost" permission
// as well as the permissions of the "author" role
$admin = $auth->createRole('admin');
$auth->add($admin);
$auth->addChild($admin, $updatePost);
$auth->addChild($admin, $author);
// Assign roles to users. 1 and 2 are IDs returned by IdentityInterface::getId()
// usually implemented in your User model.
$auth->assign($author, 2);
$auth->assign($admin, 1);
}
}
I am getting an error
`PHP Fatal error: Call to a member function createPermission()
on a non-object in var/www/commands/RbacController.php on line 14
PHP Fatal Error 'yii\base\ErrorException' with message 'Call to a member
function createPermission() on a non-object' in /var/www/commands/RbacController.php:14
while executing yii rbac/init . I am using basic template with PhpManager . I have added 'authManager' => [ 'class' => 'yii\rbac\PhpManager', ], in web.php .I am using basic template.

i Know this is a bit old, but I want to publish the solution.. at least what worked for me.
I have added 'authManager' => [ 'class' => 'yii\rbac\PhpManager', ],
in web.php
There is the mistake, since you a re running the command via console, you need to add that same line in the components section of console.php (in the same directory as web.php).
I hope this helps others who have a similar problem :D

The official documentation actually uses a php file https://github.com/yiisoft/yii2/blob/master/docs/guide/security-authorization.md

try this in your controller
$auth = new \yii\rbac\PhpManager();
// add "createPost" permission
$createPost = $auth->createPermission('createPost');
$createPost->description = 'Create a post';
$auth->add($createPost);
http://blog.dedikisme.com/blog/2014/05/09/rpbac-yii2-framework

Related

Laravel: Store error messages in database

Any one know how to send error messages to database in laravel which generate from app/exceptions/handler.php ?
I need to send what error massages generated in report() method to database.
If you are interested doing this manually, you can do something as following.
Step 1 -
Create a model to store errors that has a DB structure as following.
class Error extends Model
{
protected $fillable = ['user_id' , 'code' , 'file' , 'line' , 'message' , 'trace' ];
}
Step 2
Locate the App/Exceptions/Handler.php file, include Auth, and the Error model you created. and replace the report function with the following code.
public function report(Exception $exception) {
// Checks if a user has logged in to the system, so the error will be recorded with the user id
$userId = 0;
if (Auth::user()) {
$userId = Auth::user()->id;
}
$data = array(
'user_id' => $userId,
'code' => $exception->getCode(),
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'message' => $exception->getMessage(),
'trace' => $exception->getTraceAsString(),
);
Error::create($data);
parent::report($exception);
}
(I am demonstrating this using laravel 5.6)
Because Laravel uses Monolog for handling logging it seems that writing Monolog Handler would be the cleanest way.
I was able to find something that exists already, please have a look at monolog-mysql package. I did not use it, so I don't know whether it works and if it works well, but it's definitely good starting point.

Token cannot be null on the instantiation of the Product Query Builder. / Query Akeneo 2

I would like to create a command akeneo into my bundle who query my products like this.
So, after multiple test, i have always this error:
In ProductQueryBuilderFactory.php line 68:
Token cannot be null on the instantiation of the Product Query
Builder.
Here is my code :
$pqbFactory = $this->getApplication()->getKernel()->getContainer()->get('pim_catalog.query.product_query_builder_factory');
$pqb = $pqbFactory->create(['default_locale' => 'fr_FR', 'default_scope' => 'ecommerce']); // error
To complete Julien's answer, note that this error comes only if you are using the Enterprise Edition (EE). Indeed, in the EE, we decorate the normal product_query_builder_factory to apply permission.
If you don't want to apply permission (and don't use any token), you can use the pim_catalog.query.product_query_builder_factory_without_permission:
<?php
require __DIR__.'/vendor/autoload.php';
$kernel = new AppKernel('dev', true);
$kernel->boot();
$pqbFactory = $kernel->getContainer()->get('pim_catalog.query.product_query_builder_factory_without_permission');
$pqb = $pqbFactory->create(['default_locale' => 'fr_FR', 'default_scope' => 'ecommerce']); // you won't have any error
The PQB needs to have an authenticated user to be able to apply right filters on the results. To authenticate a user in your command you can take inspiration from the get product command. We simply take a --username argument and manually add it to the token storage.
$userManager = $this->getContainer()->get('pim_user.manager');
$user = $userManager->findUserByUsername($username);
if (null === $user) {
$output->writeln(sprintf('<error>Username "%s" is unknown<error>', $username));
return false;
}
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->getTokenStorage()->setToken($token);

yii2 RBAC for basic template role for group of users

I just want to know how can I assign roles to a group of users in yii2 using DbManager because I have seen a lot of tutorials but most of them are oriented to advance template and I'm using the basic template.
they mention folders like common, backend, that I donĀ“t find in basic template
Can you give me a tutorial or some guidance that I can follow?
thanks
Take a look at this page: http://www.yiiframework.com/doc-2.0/guide-security-authorization.html
That will help you add the DbManager for the RBAC. First you will want to create different roles and then you will need to add the permissions for the different roles.
Then when you create a user you will need to assign that user a role and they will have those permissions.
Here is a snippet from the docs for creating the roles and permissions.
<?php
namespace app\commands;
use Yii;
use yii\console\Controller;
class RbacController extends Controller
{
public function actionInit()
{
$auth = Yii::$app->authManager;
// add "createPost" permission
$createPost = $auth->createPermission('createPost');
$createPost->description = 'Create a post';
$auth->add($createPost);
// add "updatePost" permission
$updatePost = $auth->createPermission('updatePost');
$updatePost->description = 'Update post';
$auth->add($updatePost);
// add "author" role and give this role the "createPost" permission
$author = $auth->createRole('author');
$auth->add($author);
$auth->addChild($author, $createPost);
// add "admin" role and give this role the "updatePost" permission
// as well as the permissions of the "author" role
$admin = $auth->createRole('admin');
$auth->add($admin);
$auth->addChild($admin, $updatePost);
$auth->addChild($admin, $author);
// Assign roles to users. 1 and 2 are IDs returned by IdentityInterface::getId()
// usually implemented in your User model.
$auth->assign($author, 2);
$auth->assign($admin, 1);
}
}
This RbacController.php file would go inside the commands folder in the base of your project. You can run it via the terminal by calling php yii rbac/init.
Then you will actually need to check if a user has certain permissions. So when an authenticated user is performing an action you can call something like
if (\Yii::$app->user->can('createPost')) {
// create post
}
where the string bassed to the can method is the permission that you are wanting to check.

Action after loginByCookie()

In my app, I'm using session to store some user's data (e.g. name, role). I'm using default User class on common/models from yii2 and I'm getting the data I need by user id.The problem is that the data I stored in session are lost if user resume their previous session without entering password (using remember me option). To solve this, I tried to modify and put the codes for saving user's data inside validateAuthKey() method in User since it's called when yii2 checking for authkey to resume session. As in:
public function validateAuthKey($authKey)
{
$user = Member::findOne(['account_id' => Yii::$app->user->id]);
// Save on session
Yii::$app->session->set('name', $user->first_name . ' ' . $user->last_name);
Yii::$app->session->set('position', $user->position);
// .. other data
return true;
}
As you can see, I use the id of logged user to find Member. But by doing this, I got "Trying to get property of non-object" exception from Yii::$app->user->id. I can only get the id after the login process is completed. After prying around, I found that loginByCookie() from User in vendor\yiisoft\yii2\Web is used to log in. Is there any way to save user's data without tampering codes on vendor? Maybe some kind of event after loginByCookie() is executed.
Create your own User model extends \yii\web\User
namespace frontend\components;
class User extends \yii\web\User
{
protected function afterLogin($identity, $cookieBased, $duration)
{
...Do something here...
parent::afterLogin($identity, $cookieBased, $duration);
}
}
Modify the config (main.php).
'components' => [
'user' => [
'class' => 'frontend\components\User',
'identityClass' => 'common\models\User',
...
]
]
Put the below code in common/config/bootstrap.php
The EVENT_AFTER_LOGIN will be called even if the user is logged in by cookie.
use yii\web\User;
use yii\base\Event;
Event::on(User::className(), User::EVENT_AFTER_LOGIN, function() {
$user = Member::findOne(['account_id' => Yii::$app->user->id]);
// Save on session
Yii::$app->session->set('name', $user->first_name . ' ' . $user->last_name);
Yii::$app->session->set('position', $user->position);
});

how to handle errors in yii

I am working on an application using yii. I have an action let acmanageappointments/index. I have defined its rule as follow
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array('index','create','update','delete','updatestatus'),
'users'=>array('#'),
and its action is as follow :
public function actionIndex()
{
$user_id = Yii::app()->user->getId();
$criteria = new CDbCriteria();
$criteria->condition = 'user_id='.$user_id;
$count=AcAppointments::model()->count($criteria);
$pages=new CPagination($count);
//results per page
$pages->pageSize=10;
$pages->applyLimit($criteria);
$AllAppointments = AcAppointments::model()->findAll($criteria);
// Applying Global Date Time Format
$condition = array('user_id' => $user_id);
$DTFormat = CalendarSettings::model()->findByAttributes($condition);
$this->render('index',array(
'AllAppointments' => $AllAppointments,
'pages' => $pages,
'DTFormat' => $DTFormat,
));
}
This action can only be accessed with authenticated persons. when I am logged in then this function is working properly. but when I am logged out and executing this action then it gives CDbException. How can I handle this exception, and when the user is logged out and if he is trying to access this url then he should be redirected on login page . How can I do this ?
update : Here is my accessrules :
public function accessRules()
{
return array(
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array('index','create','update','delete','updatestatus'),
'users'=>array('#'),
),
array('deny', // deny all users
'users'=>array('*'),
),
);
}
and here is the error :
CDbCommand failed to execute the SQL statement: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
As topher mentioned in comments, you need a filters method.
Make sure you have this in your controller, else your access rules will do nothing:
public function filters()
{
return array(
'accessControl',
);
}
If it works, give his answer credit when he updates it with this snippet.
You need to define another rule that will ensure that non-authenticated users are denied access. This must be the last rule.
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array('index','create','update','delete','updatestatus'),
'users'=>array('#'),
),
array('deny',
'users'=>array('*'),
),
You can have an errorHandler setting in your config file "main.php"
'components'=>array(
...............
...............
'errorHandler'=>array(
// use 'site/error' action to display errors
'errorAction'=>'site/error',
),
...............
...............
)
this will redirect all the exceptions to the provided URL site/error in this case.
Check value $user_id. if you are not logged in, you get empty $user_id
$user_id = Yii::app()->user->getId();
$criteria = new CDbCriteria();
$criteria->condition = 'user_id='.$user_id;
When you execute with this criteria you got SQL error