Does anyone have a working example of this extension.
I'm talking about:
https://github.com/mdmsoft/yii2-admin
I'm looking for Yii app basic.
I installed and working properly, but I don't know how to configure "Roles" and "Rules"
At Yii 1.xxx I used http://www.yiiframework.com/extension/authbooster/ but this not working in Yii2.xx
Create a custom model AccessRules.php
<?php
namespace app\models;
class AccessRules extends \yii\filters\AccessRule
{
/**
* #inheritdoc
*/
protected function matchRole($user)
{
if (empty($this->roles)) {
return true;
}
foreach ($this->roles as $role) {
if ($role === '?') {
if ($user->getIsGuest()) {
return true;
}
} elseif ($role === '#') {
if (!$user->getIsGuest()) {
return true;
}
// Check if the user is logged in, and the roles match
} elseif (!$user->getIsGuest() && (int)$role === $user->identity->user_role) {
return true;
}
}
return false;
}
}
?>
Now in your Site Controller add the roles:
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
// We will override the default rule config with the new AccessRule class
'ruleConfig' => [
'class' => AccessRules::className(),
],
'only' => ['create', 'update', 'delete','index'],
'rules' => [
[
'actions' => ['create', 'update', 'delete','index'],
'allow' => true,
// Allow admin to create
'roles' => [
'1'
],
]
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
Related
I am working on API in Yii2, where I need to use different authentication methods for different actions.
How can I set CompositeAuth for action1, action2 and action3, and HttpBasicAuth for action4 and action5?
public function behaviors()
{
return [
'basicAuth' => [
'class' => \yii\filters\auth\HttpBasicAuth::className(),
'auth' => function ($username, $password) {
$user = User::find()->where(['username' => $username])->one();
if ($user->verifyPassword($password)) {
return $user;
}
return null;
},
],
];
}
You can attach multiple auth behaviors and use only property to specify list of actions which should be affected by each behavior:
public function behaviors() {
return [
'compositeAuth' => [
'class' => \yii\filters\auth\CompositeAuth::className(),
'authMethods' => [/* ... */],
'only' => ['action1', 'action2', 'action3'],
],
'basicAuth' => [
'class' => \yii\filters\auth\HttpBasicAuth::className(),
'auth' => function ($username, $password) {
$user = User::find()->where(['username' => $username])->one();
if ($user->verifyPassword($password)) {
return $user;
}
return null;
},
'only' => ['action4', 'action5'],
],
];
}
I've found a lot of answers on how to create Access Control that requires login to all controllers and actions.
The following post shows how I did all controllers require login:
Yii2 require all Controller and Action to login
I've used the code below under my components:
'as beforeRequest' => [
'class' => 'yii\filters\AccessControl',
'rules' => [
[
'allow' => true,
'actions' => ['login', 'error'],
],
[
'allow' => true,
'roles' => ['#'],
],
]
],
But, I want to add some exceptions to it. Some controllers need to have some actions visible to Guest.
I've tried to use this code inside my behaviors on ReportsController:
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'actions' => ['share'],
'roles' => ['?'],
],
],
]
Still get redirected to login.
I'm trying to to make actionShare($param) {} public to guests.
What am I missing?
Thanks for all your help!
First execute
yii migrate --migrationPath=#yii/rbac/migrations
from command prompt to create RBAC table in data base.
Then create RbacController in component folder
namespace app\components;
use yii;
use yii\web\Controller;
use yii\filters\AccessControl;
class RbacController extends Controller
{
public function RbacRule($modules = false)
{
$rules = false;
if ($modules){
$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 = "/$module/$controller/$action";
$post = Yii::$app->request->post();
if (\Yii::$app->user->can($route)) {
return true;
}
}
];
}else{
$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 $rules;
// return true;
}
}
then extend to your controller using this RbacController instead of controller.
use app\components\RbacController;
class AdminController extends RbacController
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
// [
// 'actions' => ['login', 'logout'],
// 'allow' => true,
// 'roles' => ['?'],
// ],
parent::RbacRule(),
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post'],
'bulk-delete' => ['post'],
],
],
];
}
.......
}
If your controller is inside Modules folder then you have to use
parent::RbacRule(TRUE) instead of parent::RbacRule(),
I am working with a lot of module in yii2 like this.
yii_basic
-- modules
-- admin
-- it
-- members
I have a scenario which is the user (members) need an approval sign via email that sending by app.
For example, this is the link : dzil.local/it/request/update?id=940 , which is this link is actually an update controller with ID.
I need user to force login when it's accessed.
But My problem is, after login is success, it 's not redirect to the controller that I mean: dzil.local/it/request/update?id=940 but to actionIndex of module.
This is the class RequestController :
class RequestController extends Controller {
public function behaviors() {
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post'],
'bulk-delete' => ['post'],
],
],
'access' => [
'class' => \yii\filters\AccessControl::className(),
'rules' => [
[
'actions' => ['create', 'update', 'delete', 'get-item-detail', 'error'],
'allow' => true,
],
[
'actions' => ['logout', 'index'], // add all actions to take guest to login page
'allow' => true,
'roles' => ['#'],
],
],
],
];
}
I think the failed it comes from this :
public function actionLogin()
{
if (!Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
if (Yii::$app->user->can('Administrator')) {
return $this->redirect(['/admin']);
} else if (Yii::$app->user->can('IT')) { // the user is on IT
return $this->redirect(['/it']);
} else { //defaultnya user common
return $this->redirect(['/members']); // the user is member
}
}
return $this->render('login', [
'model' => $model,
]);
}
Please advise me to get a best practice.
If you need a go back routing after login you should add where needed return $this->goBack(); eg:
if ($model->load(Yii::$app->getRequest()->post()) && $model->login()) {
return $this->goBack();
}
Trying to implement a GET method in Rest API, to query the user status e.g. GET user/:id/status
So getting the status of user id #1 would call /user/1/status
In config I have:
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => [
'v1/user'
],
'extraPatterns' => [
'GET status' => 'status',
],
'tokens' => [
'{id}' => '<id:\\w+>'
],
],
],
User Model:
namespace api\modules\v1\models;
use \yii\db\ActiveRecord;
class User extends ActiveRecord {
/**
* #inheritdoc
*/
public static function tableName() {
return 'user';
}
/**
* #inheritdoc
*/
public static function primaryKey() {
return [ 'id' ];
}
}
User Controller:
namespace api\modules\v1\controllers;
use yii\rest\ActiveController;
class UserController extends ActiveController {
public $modelClass = 'api\modules\v1\models\User';
public function actions() {
$actions = parent::actions();
unset(
$actions[ 'index' ],
$actions[ 'view' ],
$actions[ 'create' ],
$actions[ 'update' ],
$actions[ 'delete' ],
$actions[ 'options' ]
);
return $actions;
}
protected function verbs() {
return [
'status' => [ 'GET' ],
];
}
public function actionStatus( $id ) {
return 1;
}
}
But now I'm not sure on how to actually return the data for the call.
$user = User::findOne($id);
if ($user)
return Json::encode(['success'=>true, 'data'=>$user->status]);
else
return Json::encode(['success'=>false, 'message'=>"Can't find user"]);
I have this controller code for login:
public function actionLogin()
{
if (!\Yii::$app->user->isGuest) {
return $this->redirect(Yii::$app->request->baseUrl.'/telephone/index');
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
return $this->redirect(Yii::$app->request->baseUrl.'/telephone/index');
}
return $this->render('login', [
'model' => $model,
]);
}
And for preventing the add and delete action for unauthorized users i used:
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['add','delete'],
'rules' => [
// allow authenticated users
[
'allow' => true,
'roles' => ['#'],
],
// everything else is denied by default
],
],
];
}
But if unauthorized users clik add or delete, it is redirected to site/login. How can i change that controller and action?
There are different approaches to changing that route depending on the scope. They all involve changing the loginUrl property of the yii\web\User class.
Global
Edit config file.
'components' => [
'user' => [
'loginUrl' => ["controller/action"],
],
],
Controller/Action
Edit beforeAction method of the controller.
public function beforeAction($action)
{
// action-specific
if(in_array($action->id,['not', 'allowed', 'actions']))
Yii::$app->user->loginUrl = ["controller/action"];
// controller-wide
Yii::$app->user->loginUrl = ["controller/action"];
if (!parent::beforeAction($action)) {
return false;
}
return true;
}
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['add','delete'],
'rules' => [
'allow' => true,
'actions' => ['add','delete'],
'roles' => ['#'],
'denyCallback' => function ($rule, $action) {
return $this->redirect('index.php?r=site/login');
}
],
],
];
}