I have a question about Cake's bake for policies on models/entities named with underscore_names.
I have an app the uses Authentication and Authorization middleware, but baking the authorization policies for entities and tables on models with two_word names doesn't generate the correct code (it seems to me).
I'll try to simplify the question with a basic example I created within my app to reproduce the problem:
First, I'm using: CAKE_VERSION: 4.2.5, cakephp/authentication: 2.0, cakephp/authorization: 2.0, php: >=7.2, (also, I'm running XAMPP on windows 10)
I created these two simple models within my app to demonstrate the issue:
CREATE TABLE `dogs` (
`id` int(11) NOT NULL,
`name` varchar(16) NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=tis620;
AND
CREATE TABLE `dog_traits` (
`id` int(11) NOT NULL,
`dog_id` int(11) NOT NULL,
`trait` varchar(128) NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=tis620;
- I baked everything for these two models:
bin\cake bake all dogs
bin\cake bake policy --type entity dog
bin\cake bake policy --type table dogs
AND
bin\cake bake all dog_traits
bin\cake bake policy --type entity dog_trait
bin\cake bake policy --type table dog_traits
- For the Dogs model, everything works as expected. The Dog policy looks like this:
declare(strict_types=1);
namespace App\Policy;
use App\Model\Entity\dog;
use Authorization\IdentityInterface;
class dogPolicy
{
/**
* Check if $user can create dog
*
* @param Authorization\IdentityInterface $user The user.
* @param App\Model\Entity\dog $dog
* @return bool
*/
public function canCreate(IdentityInterface $user, dog $dog)
{
if ($user) {
return true;
}
return false;
}
// Etc....
}
Then in the Dogs controller:
public function add()
{
$dog = $this->Dogs->newEmptyEntity();
$this->Authorization->authorize($dog, 'create');
if ($this->request->is('post')) {
//Etc....
This works as expected, no problem.
- However, for all my models that have underscored names, (such as dog_traits), the baked policy doesn't seem to work properly.
Here is what the default baked
DogTraitPolicy.php
looks like:
declare(strict_types=1);
namespace App\Policy;
use App\Model\Entity\dog_trait;
use Authorization\IdentityInterface;
class dog_traitPolicy
{
/**
* Check if $user can create dog_trait
*
* @param Authorization\IdentityInterface $user The user.
* @param App\Model\Entity\dog_trait $dogTrait
* @return bool
*/
public function canCreate(IdentityInterface $user, dog_trait $dogTrait)
{
if ($user) {
return true;
}
return false;
}
//ETC....
}
Then in DogTraits Controller:
public function add()
{
$dogTrait = $this->DogTraits->newEmptyEntity();
$this->Authorization->authorize($dogTrait, 'create');
if ($this->request->is('post')) {
//Etc....
So now the URL http://localhost/myapp/dog-traits/add throws the error:
Policy for App\Model\Entity\DogTrait has not been defined.
If I go back to DogTraitPolicy.php and change the class name to class dogTraitPolicy
(camelcased rather than underscored), the I get the error:
Argument 2 passed to App\Policy\dogTraitPolicy::canCreate() must be an instance of App\Model\Entity\dog_trait, instance of App\Model\Entity\DogTrait given, called in C:\xampp\htdocs\myapp\vendor\cakephp\authorization\src\AuthorizationService.php on line 93
If I change the canCreate method to this (notice the camelcased argument name):
public function canCreate(IdentityInterface $user, dogTrait $dogTrait)
{
if ($user) {
return true;
}
return false;
}
Then this returns the error:
Argument 2 passed to App\Policy\dogTraitPolicy::canCreate() must be an instance of App\Policy\dogTrait, instance of App\Model\Entity\DogTrait given, called in C:\xampp\htdocs\myapp\vendor\cakephp\authorization\src\AuthorizationService.php on line 93
If I then remove the argument name dogTrait before $dogTrait, then the policy authorizes as expected.
public function canCreate(IdentityInterface $user, $dogTrait)
{
if ($user) {
return true;
}
return false;
}
So the question is: Is entity policy bake working correctly for underscored model names? It works correctly out of the box for singleword models, but doesn't for underscored_names. Am I missing something?
Thanks in advance for any advice.
Use bake commands with 'cased' class names instead of underscored table names, eg: