Baked Entity Policies for underscore_named models

202 Views Asked by At

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:

  1. 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)

  2. 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;
  1. 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
  1. 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.

  1. 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.

1

There are 1 best solutions below

0
On

Use bake commands with 'cased' class names instead of underscored table names, eg:

bin\cake bake all DogTraits
bin\cake bake policy --type entity DogTrait
bin\cake bake policy --type table DogTraits