An easy way to load ACL in Zend Framework 2? - acl

I have been following this guide to load my menu configuration and i think it is very nice and clean way to load the menu.
My question is simple, is there a way to load your ACL configuration on the same way with a config array and some kinda of factory?
If there isn't, how do i load a ACL configuration and use with that menu in a easy way?
Thanks!
Edit:
This is a very good blog post on why use modules that is already done and not make your own, http://hounddog.github.com/blog/there-is-a-module-for-that/

ZF2 contains ACL and also RBAC (role based ACL - might be in ZF2.1), but to put it in place, easier is to use module which you can plug into your application. BjyAuthorize seems to me a bit bloated, you have to use ZfcUser module. I prefer ZfcRbac, the ACL rules are based on user roles (group) and their access to controller, action or route. Configuration stored in one config file, really easy to implement.

Most likely there are several ways to do it, but I prefer to do it in getViewHelperConfig() of application's Module.php (here I use BjyAuthorize module to simplify work with ACL, and in particular it allows to set ACL rules in configuration file module.bjyauthorize.global.php)
public function getViewHelperConfig()
{
return array(
'factories' => array(
'navigation' => function($sm) {
$auth = $sm->getServiceLocator()->get('BjyAuthorize\Service\Authorize');
$role = $auth->getIdentityProvider()->getIdentityRoles();
if (is_array($role))
$role = $role[0];
$navigation = $sm->get('Zend\View\Helper\Navigation');
$navigation->setAcl($auth->getAcl())->setRole($role);
return $navigation;
}
)
);
}

Play with This structure . get role and resource from database and save this in session for or any caching .

You are right, there is no out-of-the-box-all-in-one solution. You have to build some bridges between the modules.
Another easy way to integrate BjyAuthorize is using **Zend Navigation**s default methods as described by Rob Allen:
Integrating BjyAuthorize with ZendNavigation
$sm = $e->getApplication()->getServiceManager();
// Add ACL information to the Navigation view helper
$authorize = $sm->get('BjyAuthorizeServiceAuthorize');
$acl = $authorize->getAcl();
$role = $authorize->getIdentity();
ZendViewHelperNavigation::setDefaultAcl($acl);
ZendViewHelperNavigation::setDefaultRole($role);
You can also use ZfcRbac and use a listener to make it work with Zend Navigation.
Since this is a lot of code I simply post the link here:
Check Zend Navigation page permissions with ZfcRbac – Webdevilopers Blog

I've just created an ACL module that creates an ACL Service parsing the routes.
To manage your access control to your application you only need to define roles and add a new key 'roles' in every route. If you do not define that key or its array is empty, then the route becomes public. It also works with child routes.
As an example:
array(
'router' => array(
'routes' => array(
'user\users\view' => array(
'type' => 'Segment',
'options' => array(
'route' => '/admin/users/view/id/:id/',
'constraints' => array(
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'User\Controller\Users',
'action' => 'view',
'roles' => ['admin', 'user'],
),
),
),
),
),
);
The module can be installed via composer and it is now listed in the zend modules repository: http://zfmodules.com/itrascastro/TrascastroACL
You can get more detailed info about use and installation from my blog: http://www.ismaeltrascastro.com/acl-module-zend-framework/

Related

How to change default template in Yii2?

I am using the Yii 2 Advanced Application Template, the AdminLTE Asset Bundle and the Gii code generator.
Here is my example:
I need to change the template so I can remove the "Create Lab Tipos Movimientos" button (and modify some things more).
I am removing every button after Gii create the CRUD but I would like to change the template so Gii can do it automatically.
Once you have create your own template for gii
You can change the default template for gii assigning the new template values in main.php (main-local.php)
assigning the proper parameter to gii module
.....
$config['modules']['gii'] = [
//'class' => 'yii\gii\Module',
'class' => 'your_gii_module_path\Module',
'allowedIPs' => ['127.0.0.1', '::1', ],
'generators' => [ //here
'crud' => [ // generator name
//'class' => 'yii\gii\generators\crud\Generator', // generator class
'class' => 'your_gii_module_path\generators\crud\Generator', // generator class
'templates' => [ //setting for out templates
// template name => path to template
'your_crud_entry' => 'your_absolute_path_\your_gii_module_path\generators\crud\default',
]
]
],
];
.......
I have not done it myself, but I found this Guide by SamDark in Github that explains how to create your own template. This is the url: https://github.com/yiisoft/yii2-gii/blob/master/docs/guide/topics-creating-your-own-templates.md
Additionally, if you just want to eliminate the "Create Lab Tipos Movimiento" button you can try modifying the current template which if I am not wrong is located inside the folder vendor/yiisoft/yii2-gii/generators/crud/default/views and the file should be index.php. There you can try deleting or better yet commenting the part of the code that says:
<p>
<?= "<?= " ?>Html::a(<?= $generator->generateString('Create ' . Inflector::camel2words(StringHelper::basename($generator->modelClass))) ?>, ['create'], ['class' => 'btn btn-success']) ?>
</p>
I suggest you to make a copy of the files you modify just in case anything goes wrong.
Hope this helps you.
Have a great day.
EDIT:
Additionally following the answer of schmunk to a very similar question in stack overflow found here: How to use custom templates in gii (using Yii 2)
There is apparently a Gii extension in beta phase to help you in this situation called yii2-giiant found here: https://github.com/schmunk42/yii2-giiant (maybe there are similar extensions that are in a more advanced phase of development, google search should help with that)

How to use telegram api package in CakePHP 3?

I tried to use PHP telegram bot in my CakePHP 3 website, but encountered many problems.
done
I ran "composer require longman/telegram-bot" and copied package to "plugins" folder.
and then "bin/cake plugin load longman/telegram-bot".
questions
1. Where I must put the package and why? vendor or plugins
2. How to call package methods in URL?
I added "index" method to "telegram-bot/src/Telegram.php" and tried this snippet code in my "Template/Users/index.ctp".
echo $this->Html->link('telegram', ['plugin' => 'longman/telegram-bot', 'controller' => 'telegram', 'action' => 'index']);
that results
Error: A route matching "array ( 'plugin' => 'longman/telegram-bot', 'controller' => 'telegram', 'action' => 'index', '_ext' => NULL, )" could not be found.
3. What I must add to "routes.php"?
4. How can I use "telegram-bot/src/Telegram.php" methods in my controllers and models.
5. Is there anything else that must be observed?
Thanks.

Symfony2 - ChoiceType - get choice list from JSON without JS

I have a JSON file with all world languages and would like to put them into choices array inside ChoiceType form field.
$builder->add('languages', ChoiceType::class, array(
'choices' => array()
))
My JSON file is stored: projectname/web/bundles/index/json/languages.json
Is it possible to achieve it without writing JS / AJAX?
P.S. EventListeners or other alternatives that Symfony2 provides suits me well.
You could reach the file with DIR, since I dont' know where the php file with builder is located, it could looks like:
$builder->add('languages', ChoiceType::class, array(
'choices' => json_decode(
//if builder is in controller, this should work
file_get_contents(__DIR__.'/../../../web/bundles/index/json/languages.json'),
true)
));

Yii2 load all models automatically

I don't like to declare every model as
use app\models\Country;
Really it bothers me a lot. I like the approach used in Yii 1.15 when you could load all models using import instruction in config like:
'import' => array(
'application.models.*',
)
Yes, I know it's not good for performance. But I have not more than 50 models and I care much more about my own performance rather than of performance of machine.
I had no luck in figuring out how to do it Yii2.
All I found out is that it should be done via bootstrap option in main config file.
I tried the following:
$config = [
'language' => 'en',
'id' => 'basicUniqueApp',
'basePath' => dirname(__DIR__),
'bootstrap' => [
'log',
'app\models\*'
],
But it's not proper syntax.
Any ideas?
You're trying to break down PHP namespace. That's not a good idea.
If you don't want declare on top model, You can call directly without declare like this:
$country = new \app\models\Country();

Use a widget in a statically-called method

Normally a widget is used by calling CController::widget() on an instance of CController, typically $this in a view.
But if I'm writing a static method, a helper, say, then I don't have access to an instance of CController. So how do I use a widget?
Let's say further that this helper method is invoked in the eval()’ed expression in a CDataColumn's value property. That poor expression has almost no context at all. How should the helper use a widget?
EDIT: Code example
As requested, a view example:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $model->search(),
'columns' => array(
array(
'name' => 'attrName',
'value' => '--USE WIDGET HERE--',
),
)
));
This answer doesn't answer the question in general but in the specific case—how to access the controller and use a widget in the context of the evaluated expression of CDataColumn::$value—you can use this:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $model->search(),
'columns' => array(
array(
'name' => 'attrName',
'value' => function ($data, $row, $column) {
$controller = $column->grid->owner;
$controller->widget(/* ... etc ... */);
},
),
)
));
The trick was discovering that CDataColumn::renderDataCellContent() uses CComponent::evaluateExpression(), which injects the component instance into the callback as the last parameter. In this case that omponent is the CDataColumn, which references the controller as shown.
I don't like writing PHP expressions as string literals so I'm pleased to find this option.
A comment on http://www.yiiframework.com/doc/api/1.1/CDataColumn#value-detail shows another way to us a widget in a column value that I haven't tried.
This one is working solution for calling widgets in static methods in Yii
Yii::app()->controller->widget('widget');
There's no direct way to call a widget out of controller because you shouldn't do so. It's all about MVC. Widgets are only needed and/or useful in views, and views are only accessed via controllers. That's the theory.
I guess you're approaching the problem mistakenly. A proper, MVC-friendly way to do what your're trying to do involves using renderPartial(). You know: you a have certain content and you want to decorate it (in your case you want to imbibe it inside a widget, right?) before displaying it to final user; so, from the view, you call renderPartial(). It will send your data to a file where it will properly decorated. renderPartial() returns the content properly formatted and now you can display it in the view.
Unfortunately, in your particular case, you're working with grid view (right?) and, at least from my point of view, it makes the things a bit harder. In order to decorate content for a CGridColumn-subclass element (like CDataColumn), you need to override the renderDataCellContent() method. Check it out here: http://www.yiiframework.com/doc/api/1.1/CDataColumn#renderDataCellContent-detail