access rules by IP for all roles - yii

on Yii2, I'm trying to limit the create action to only allow approved IPs no matter if user is logged in or not.
Here is my code
'access' => [
'class' => AccessControl::className(),
'only' => ['index', 'view', 'create'],
'rules' => [
[
'actions' => ['index','view'],
'allow' => true,
'roles' => ['#'],
],
[
'actions' => ['create'],
'allow' => true,
'ips' => Yii::$app->params['adminIPs'],
'roles' => ['?','#'],
],
],
],
if the user is logged in, and is not an allowed ip. It shows the forbidden permission page but if the user if NOT logged in, it redirects to the login page.
How do i get it to show the 403 forbidden page for both scenarios?

By default, when the rule denies access the AccessControl::denyAccess() method is called. If the user is guest (not logged in) they are redirected to login page by this method. If you want to return 403 Forbidden page instead you have to override this behavior by using AccessRule::$denyCallback property.
Also, you need to set the denyCallback property for rule that denies access, not for the one that allows access.
For example:
'access' => [
'class' => AccessControl::class,
'only' => ['index', 'view', 'create'],
'rules' => [
// ...
[
'actions' => ['create'],
'allow' => true,
'ips' => Yii::$app->params['adminIPs'],
],
[
'actions' => ['create'],
'allow' => false,
'denyCallback' => function() {
throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
}
]
],
],
Because the rule matches everything, you need to make sure that it's last rule for create action next rules won't be reached once this one matches.

If you're wanting to restrict access by IP and don't care if the user is logged in or not you can just omit the roles.
'access' => [
'class' => AccessControl::className(),
'only' => ['index', 'view', 'create'],
'rules' => [
//....
[
'actions' => ['create'],
'allow' => true,
'ips' => Yii::$app->params['adminIPs'],
],
],
],

Related

How to disable a particular config component on specific action in YII2?

i have a user component in my web config file which is working fine.
$config = [
'components' => [
'user' => [
'class' => 'common\components\User'
],
...
],
];
except on a page where I want to use a different user file. Is it possible to disable the particular component in Yii for a particular action?
There are several ways foe example You could declare two different components
$config = [
'components' => [
'user' => [
'class' => 'common\components\User'
],
'user1' => [
'class' => 'common\components\MyAlternativeUser'
],
...
],
];

How to Alias one of the table sql in cakephp 3.6.3

I'm trying to access Contacts. I'm getting below error
Error: SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'Contacts'
If you are using SQL keywords as table column names, you can enable identifier quoting for your database connection in config/app.php.
Check SQL Query Screenshot
How do I setAlias() in table associations ?
ContactsController.php
public function index()
{
$this->paginate = [
'contain' => ['Users', 'Contacts', 'SourceProspects', 'Status',
'Secteurs', 'Products']
];
$contacts = $this->paginate($this->Contacts);
$this->set(compact('contacts'));
}
public function view($id = null)
{
$contact = $this->Contacts->get($id, [
'contain' => ['Users', 'Contacts', 'SourceProspects', 'Status',
'Secteurs', 'Products', 'Leads', 'Accounts']
]);
$this->set('contact', $contact);
}
ContactsTable.php
$this->setTable('contacts');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Users', [
'foreignKey' => 'user_id'
]);
$this->belongsTo('Contacts', [
'foreignKey' => 'contact_type_id'
]);
$this->belongsTo('Leads', [
'foreignKey' => 'lead_id'
]);
$this->belongsTo('SourceProspects', [
'foreignKey' => 'source_prospect_id'
]);
$this->belongsTo('Accounts', [
'foreignKey' => 'account_id'
]);
$this->belongsTo('Status', [
'foreignKey' => 'statut_id'
]);
$this->belongsTo('Secteurs', [
'foreignKey' => 'secteur_id'
]);
$this->belongsTo('Products', [
'foreignKey' => 'product_id'
]);
$this->hasMany('Accounts', [
'foreignKey' => 'contact_id'
]);
$this->hasMany('Leads', [
'foreignKey' => 'contact_id'
]);
}
The problem seems to be in ContractsTable here
$this->belongsTo('Contacts', [
'foreignKey' => 'contact_type_id'
]);
in this way cake join the Contacts table with itself so creating a non unique alias
maybe is just a typo and you wanted to do
$this->belongsTo('ContactTypes', [
'foreignKey' => 'contact_type_id'
]);
but if you actually want to use that relationship then you have to alias the joined Contacts table
$this->belongsTo('ParentContacts', [ // choose your alias here
'className' => 'Contacts'
'foreignKey' => 'contact_type_id'
]);
so every time you have to refer to the joined table you can do something like
'contain' => [
...,
'ParentContacts',
],

yii2:Call to undefined method Closure::allows() in denyCallback

i use Yii2 framework
this is my behaviors function in ShippingController
public function behaviors()
{
return [
'access' => [
'class' => \yii\filters\AccessControl::className(),
'rules' => [
// deny all POST requests
// [
// 'actions' => ['index', 'create'],
// 'allow' => TRUE,
// ],
[
'actions' => ['index', 'create', 'init'],
'allow' => true,
'roles' => ['?'],
'matchCallback' => function ($rule, $action)
{
return $action->controller->redirect('action');
}
],
'denyCallback' => function ($rule, $action)
{
return $action->controller->redirect('not');
}
// everything else is denied
],
],
];
}
matchCallback is worked good but
indenyCallback i have this error :
Error
Call to undefined method Closure::allows()
what is my problem ???!
move denyCallback element outside of the rules array
it needs to be on the same level with class and rules

Yii1 single login in mutlilingual site ( two domaines)

I got two domains for a mutlilingual site :www.monsite.fr and www.mysite.com
they use the same app and same databas.
i made a htaccess redirection.
But when you log yourself in the www.monsite.fr you aren't logged in www.mysite.com .
How can i do to make the session cookie valid for both ?
You need to create separate domain just for your cookies i.e.:
cookie.monsite.com
Then you need to set proper cookie domain in your configuration (Yii 2 example):
// ...
'components' => [
// ...
'user' => [
// ...
'identityCookie' => [
'name' => '_identity',
'httpOnly' => true,
'domain' => 'cookie.monsite.com',
],
],
'session' => [
// ...
'cookieParams' => [
'domain' => 'cookie.monsite.com',
'httpOnly' => true,
],
],
'request' => [ // optional
// ...
'csrfCookie' => [
'domain' => 'cookie.monsite.com',
'httpOnly' => true,
],
],

Yii2 : Setting Access Control filter to redirect after forbidden

I have a controller that use AccessControl in behaviors function like this :
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['login', 'error'],
'allow' => true,
],
[
'actions' => ['logout', 'index'],
'allow' => true,
'roles' => ['#'],
'matchCallback' => function(){
return (Yii::$app->user->identity->ROLE_ID=='1');
}
],
],
],
];
}
In my application there a 2 role, admin and user, role_id 1 is admin and role_id 2 is staff, both can access /app/administrator so I filter with that. And when I log in with staff, it shows forbidden page.
I want to redirect back in log in page when the user that log in isn't admin. Maybe I must add script in AccessControl options. So, what can i do? Thanks
You need to specify denyCallback to achieve this.
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
//your access rules
],
'denyCallback' => function($rule, $action) {
//redirection here
}
],
];
}
Note that this denyCallback will be called every time when access is denied. If you want rule-specific denyCallback e.g. you want different application behavior, then you need to specify it like this:
'rules' => [
//other rules
[
'actions' => ['index'],
'allow' => false,
'roles' => ['#'],
'matchCallback' => function(){
return (Yii::$app->user->identity->ROLE_ID == 2);
},
'denyCallback' => function(){
//redirect here
}
],
],
Here we explicitly disallow access to index action to users with ROLE_ID == 2 and redirecting them.