Your Location is: Home > Php

User Access Control Different Controller & View

From: Slovenia View: 4278 user3657273 

Question

I'm fairly new to this framework (Yii2). I'm using Yii Basic fyi. So I've been trying to give access control over different user which when they attempt to login, it will maneuver them to different layouts which dependent on their own controller.

Meaning by default Guest will be directed to the login page (default View = layout-main and Controller = SiteController). And I've done that as stated below in web.php. Not under component but new line of code below component...

'component' => [
],
'as beforeRequest' => [
   'class' => 'yii\filters\AccessControl',
   'rules' => [
       [
           'allow' => true,
           'actions' => ['login'],
       ],
       [
           'allow' => true,
           'roles' => ['@'],
       ],
   ],
   'denyCallback' => function() {
       return yii::$app->response->redirect([site/login]);
   },
]

Now I've 2 more Controllers and 2 more Layouts, one for Admin and the other one for supplier. So...

Admin:-
Controller - AdminController
View - layout/admin/main

Supplier:-
Controller - SupplierController
View - layout/supplier/main

and the default controller and layout is for login page only as below:-

Controller - SiteController
View - layout/main

So at the moment, I've just been able to redirect all that is 'Guest' to login page if they are not 'Aunthenticated'. Now, I want 'admin' to redirect to their specific Controller & View. As well as 'supplier' to theirs too.

How can I do that from here?

By the way, below are my 'User' models currently, which I named it as 'LoginProfile':-

namespace app\models;

use Yii;
use yii\base\NotSupportedException;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;

/**
* This is the model class for table "login_profile".
*
* @property int $login_profileID
* @property string $username
* @property string $auth_key
* @property string $password_hash
* @property string|null $password_reset_token
* @property string $email
* @property int $status
* @property int|null $special_question_ID
* @property string|null $special_answer
* @property int|null $login_type_ID
* @property int|null $status_login_ID
* @property int $created_at
* @property int $updated_at
* @property string $password write-only password
*
* @property LoginType $loginType
* @property SpecialQuestion $specialQuestion
* @property StatusLogin $statusLogin
*/
class LoginProfile extends \yii\db\ActiveRecord implements IdentityInterface
{
    const STATUS_DELETED = 0;
    const STATUS_ACTIVE = 10;

    /**
    * {@inheritdoc}
    */
    public static function tableName()
    {
        // return 'login_profile';
        return '{{%login_profile}}';
    }

    /**
    * @inheritdoc
    */
    public function behaviors()
    {
        return [
            TimestampBehavior::className(),
        ];
    }

    /**
    * {@inheritdoc}
    */
    public function rules()
    {
        return [
            ['status', 'default', 'value' => self::STATUS_ACTIVE],
            ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
        ];
    }

    /**
    * @inheritdoc
    */
    public static function findIdentity($id)
    {
        return static::findOne(['login_profileID' => $id, 'status' => self::STATUS_ACTIVE]);
    }

    /**
    * @inheritdoc
    */
    public static function findIdentityByAccessToken($token, $type = null)
    {
        throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
    }

    /**
    * Finds user by username
    *
    * @param string $username
    * @return static|null
    */
    public static function findByUsername($username)
    {
        return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]);
    }

    /**
    * @inheritdoc
    */
    public function getId()
    {
        return $this->getPrimaryKey();
    }

    /**
    * @inheritdoc
    */
    public function getAuthKey()
    {
        return $this->auth_key;
    }

    /**
    * @inheritdoc
    */
    public function validateAuthKey($authKey)
    {
        return $this->getAuthKey() === $authKey;
    }

    /**
    * Validates password
    *
    * @param string $password password to validate
    * @return bool if password provided is valid for current user
    */
    public function validatePassword($password)
    {
        return Yii::$app->security->validatePassword($password, $this->password_hash);
    }

    /**
    * Generates password hash from password and sets it to the model
    *
    * @param string $password
    */
    public function setPassword($password)
    {
        $this->password_hash = Yii::$app->security->generatePasswordHash($password);
    }

    /**
    * Generates "remember me" authentication key
    */
    public function generateAuthKey()
    {
        $this->auth_key = Yii::$app->security->generateRandomString();
    }

    /**
    * @return \yii\db\ActiveQuery
    */
    public function getLoginType()
    {
        return $this->hasOne(LoginType::className(), ['login_typeID' => 'login_type_ID']);
    }

    /**
    * @return \yii\db\ActiveQuery
    */
    public function getSpecialQuestion()
    {
        return $this->hasOne(SpecialQuestion::className(), ['special_questionID' => 
        'special_question_ID']);
    }

    /**
    * @return \yii\db\ActiveQuery
    */
    public function getStatusLogin()
    {
        return $this->hasOne(StatusLogin::className(), ['status_loginID' => 'status_login_ID']);
    }

    /**
    * {@inheritdoc}
    * @return LoginProfileQuery the active query used by this AR class.
    */
    public static function find()
    {
        return new LoginProfileQuery(get_called_class());
    }
}

And I've function getLoginType() which is a foreign key in database user table aka login_profile in my case that holds:-

'login_type_ID' -> 1, equals to Admin
'login_type_ID' -> 2, equals to Supplier

So I'm thinking of using this function to identify the type of user that attempted to login and give them access to specific layout/main and controller dependent on what kind of type of user they are (Admin or Supplier).

At the moment, this is my behaviour function and login & logout function in SiteController:- I need to edit this too so that it will redirect or maneuver Authenticated user to their specific page.

public function behaviour()
{
    return [
         'access' => [
             'class' => AccessControl::className(),
             'only' => ['logout'],
             'rules' => [
                 [
                     'action' => ['logout'],
                     'allow' => true,
                     'roles' => ['@'],
                 ],
             ],
         ],
         'verbs' => [
             'class' => VerbFilter::className(),
             'actions' => [
                 'logout' => ['post'],
             ],
         ],
    ];
}

/**
* {@inheritdoc}
*/
public function actions()
{
    return [
        'error' => [
            'class' => 'yii\web\ErrorAction',
        ],
        'captcha' => [
            'class' => 'yii\captcha\CaptchaAction',
            'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
        ],
    ];
}

/**
* Login action.
*
* @return Response|string
*/
public function actionLogin()
{
    if (!Yii::$app->user->isGuest) {
        return $this->goHome();
    }

    $model = new LoginForm();
    if ($model->load(Yii::$app->request->post()) && $model->login()) {
        return $this->goBack();
    }

    $model->password = '';
    return $this->render('login', [
        'model' => $model,
    ]);
}

/**
* Logout action.
*
* @return Response
*/
public function actionLogout()
{
    Yii::$app->user->logout();

    return $this->goHome();
}

And don't worry, I already change the component/user details to LoginProflie in web.php as shown below:-

'components' => [
    'user' => [
         'identityClass' => 'app\models\LoginProfile',
         'enableAutoLogin' => true,
    ],
],

Can you guys help me with this? Any suggestion on how I can do this more flexible are most welcome.

Best answer