redirect in before action is running infinitely in yii2 - yii2

i have added access filter to web.php and in login action consists following code
public function actionLogin() {
return $this->render('loginform', ['model' => $model, 'iv' => $iv, 'key' => $key]);
}

In Yii2 you don't have to do workarounds like that to achieve checking if user is logged in. Yii2 has own Access Controll behaviours, which will do all for you.
To use it, add in your controller this behaviour:
public function behaviors()
{
return [
'access' => [
'class' => yii\filters\AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['#']
],
],
],
];
}
It will check if user whos trying access all actions in this controller is logged in. For more options you should look here: YIi2 - Access Control Filter

Related

Override Yii2 Swiftmailer Recipient

I need to override the recipient email for every instance of Swiftmailer's send() function throughout my Yii2 application. This is for the purpose of load testing.
Is there an easy way to do this? Or at least a way to do it without editing Swiftmailer's vendor files?
If this is for test only why not set useFileTransport so emails will be saved in the folder of your choice instead of being sent. To do so configure it like this:
'components' => [
// ...
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'useFileTransport' => true,
],
],
This will save all emails in the #runtime/mail folder, If you want different one set:
'mailer' => [
// ...
'fileTransportPath' => '#runtime/mail', // path or alias here
],
If you want to still send emails and override recipients you can for example extend yii\swiftmailer\Mailer class.
class MyMailer extends \yii\swiftmailer\Mailer
{
public $testmode = false;
public $testemail = 'test#test.com';
public function beforeSend($message)
{
if (parent::beforeSend($message)) {
if ($this->testmode) {
$message->setTo($this->testemail);
}
return true;
}
return false;
}
}
Configure it:
'components' => [
// ...
'mailer' => [
'class' => 'namespace\of\your\class\MyMailer',
// the rest is the same like in your normal config
],
],
And you can use it in the same way you use mailer component all the time. When it's time to switch to test mode modify the configuration:
'mailer' => [
'class' => 'namespace\of\your\class\MyMailer',
'testmode' => true,
'testemail' => 'test222#test.com', // optional if you want to send all to address different than default test#test.com
// the rest is the same like in your normal config
],
With this, every email will be overridden with your recipient address.

Yii2 Yii::$app->user->identity->id returns an error instead of redirecting to login page

in my behaviours I have specified that actionList can only be viewed by authenticated users.
$behaviors [ 'access' ] = [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => [ 'list' ],
'allow' => ['#'],
]
],
];
In actionList I'm getting the user_id:
public function actionList() {
$user_id = \Yii::$app->user->identity->id;
return $this->render( 'list' );
}
All good, but if you go to this action when not logged in, you get an error:
PHP Notice – yii\base\ErrorException
Trying to get property of non-object
Makes sense, I'm not logged in so I don't have a user id, but why does the code go that far? If I comment the $user_id = \Yii::$app->user->identity->id; out, I get redirected to the login page, which is the expected behaviour. I don't think I should have to do yet another check to see if someone is logged in in the action itself, shouldn't that be handled by the behaviours['access'] beforehand?
Try this changing the allow and roles attributes:
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['list'],
'allow' => true,
'roles' => ['#'],
],
], // rules
], // access
];
}
More info here.
Here is my cent to the already good answers above
Add following code to the main controller file in your project (not the base controller) but some controller above this which is base for every other controller
/**
* Check if user is logged in and not logged out
*
* #param type $action
* #return type
*/
public function beforeAction($action) {
$this->enableCsrfValidation = false;
if(!empty($action) && $action->actionMethod == 'actionLogin') {
return true;
}
/* Check User's Login Status */
if (is_null(Yii::$app->user->identity)) {
$this->redirect(Url::to(['../site/login']));
Yii::$app->end();
}
return true;
}

Yii2 multi captcha in one page

I have a page that contains multi captcha in separated forms form example login and register modals , etc.
if I use below codes the problem is that when refresh one captcha then another captcha will be unusable because they use same session varible:
1) Login
login modal (view):
echo Captcha::widget([
'id' => 'Login-captcha',
'name' => 'LoginModel[captcha]',
'captchaAction' => '/site/captcha'
]);
LoginModel :
public function rules()
{
return [
['captcha', 'captcha'],
];
}
2) Register
register modal (view):
echo Captcha::widget([
'id' => 'register-captcha',
'name' => 'RegisterModel[captcha]',
'captchaAction' => '/site/captcha'
]);
RegisterModel:
public function rules()
{
return [
['captcha', 'captcha'],
];
}
to solve session problem I used different captcha actions to set different session variables:
1)Login
login modal view:
echo Captcha::widget([
'id' => 'Login-captcha',
'name' => 'LoginModel[captcha]',
'captchaAction' => '/site/captcha-login'
]);
LoginModel :
public function rules()
{
return [
['captcha', 'captcha', 'captchaAction' => 'site/captcha-login',],
];
}
2) Register
register modal (view):
echo Captcha::widget([
'id' => 'register-captcha',
'name' => 'RegisterModel[captcha]',
'captchaAction' => '/site/captcha-register'
]);
RegisterModel:
public function rules()
{
return [
['captcha', 'captcha', 'captchaAction' => 'site/captcha-register',],
];
}
until now everything is ok but when I move sessions from regular php files to database by below config in commponent section of main config file:
'session' => [
'class' => 'yii\web\DbSession',
],
then captchas in the first page load not works and have to refresh them to work correctly.
what is the problem?
Try this, it is for yii1 but you can get the idea, more detail
public function rules()
{
return array(
...
array('verifyCode1', 'captcha', ...
array('verifyCode2', 'verifycaptcha2', ...
);
}
public function verifycaptcha2($attribute, $params)
{
$captcha2 = Yii::app()->getController()->createAction('captcha2nd');
if (!$captcha2->validate($this->verifyCode2, false))
{
$this->addError('verifyCode2', 'invalid captcha.');
}
}
Also see this

Yii2: Method not allowed arror while logout action from different controller

When i am executing logging out action from
....index.php?r=teams/dashboard
it is throwing me #405 method not allowed error. DO i have to implement logout method other than site controller.. i.e in teams controller????
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
this action does not accept Get method, you should send it as Post OR remove it from VerbFilter.
<?= Html::a('Logout', ['/user/logout'], ['data-method'=>'post']) ?>

Redirect user to previous page after auth (yii2)

I have the main controller from which the others are inherited. Code is something like this
public function init()
{
$this->on('beforeAction', function ($event) {
...
if (Yii::$app->getUser()->isGuest) {
$request = Yii::$app->getRequest();
// dont remember login page or ajax-request
if (!($request->getIsAjax() || strpos($request->getUrl(), 'login') !== false)) {
Yii::$app->getUser()->setReturnUrl($request->getUrl());
}
}
}
...
});
}
It works perfectly for all pages, except the page with captcha. All the pages with captcha are redirected to something like this - /captcha/?v=xxxxxxxxxxxxxx
If the object is logged Yii::$app->getRequest() then I see that for pages with captcha it is used twice. For the first time the object is corect, and the second time I see the object with captcha.
How can I solve this problem with yii? Is there a chance not to track the request for captcha?
The default (generated) controller uses something like this:
public function actions()
{
return [
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
],
];
}
Does your controller contain something like this?
This means that there is an action "captcha" that is used for displaying captchas (it returns the image). When you have a page displaying a captcha the image is called after the page you want to return to. Therefore that latest page visited is the one with the captcha.
I think you have to filter out this action.
Another possibility could be to use the default $controller->goBack() method. I think this handles registering of the returnUrl by default.
Reference: Class yii\web\Controller
Guid security authorization
Use Access Control Filter(ACF) in your controller.
use yii\web\Controller;
use yii\filters\AccessControl;
class SiteController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['login', 'logout', 'signup'],
'rules' => [
[
'allow' => true,
'actions' => ['login', 'signup'],
'roles' => ['?'],
],
[
'allow' => true,
'actions' => ['logout'],
'roles' => ['#'],
],
],
],
];
}
// ...
}