I have simple role-based access set up in my Yii2 application that works like this:
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'ruleConfig' => [
'class' => AccessRule::className(),
],
'only' => ['logout', 'contact', 'change-password'],
'rules' => [
[
'actions' => ['login'],
'allow' => true,
'roles' => ['?'],
],
[
'actions' => ['logout', 'contact', 'change-password'],
'allow' => true,
'roles' => [
User::ROLE_USER,
User::ROLE_ADMIN
],
],
[
'actions' => ['logout', 'change-password'],
'allow' => true,
'roles' => [
User::ROLE_NEW_USER
],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
When users are not logged in, attempting to access the logout, contact, or change-password pages will redirect to the login page. I would also like to configure this so that users with role ROLE_NEW_USER are always redirected to the change-password page until their status changes (the status is updated in the database when the password is changed).
Is it possible to do this with denyCallback, or is there a way to use the redirect to the login page to redirect to other pages?
As in documentation:
Access rules support many options. You may also extend yii\filters\AccessRule to create your own customized access rule classes.
This allows you create a custom rule that checks if user has´n change password yet and redirect wherever you want
Okay, after some mucking about, I managed to get it working with the beforeAction() function:
public function beforeAction($action)
{
if (Url::current() != Url::toRoute('site/change-password')
&& isset(Yii::$app->user->getIdentity()->role)
&& Yii::$app->user->getIdentity()->role == User::ROLE_NEW_USER) {
return Yii::$app->getResponse()->redirect(Url::toRoute('site/change-password'));
}
if (!parent::beforeAction($action)) {
return false;
}
return true;
}
Make sure you include Url::current() != Url::toRoute('site/change-password') or you end up in a redirect loop.