Question about authorisation and policies

Need some help - tying myself in knots with authorisation logic…

Slowly rewriting a CakePHP 2 app in 4. We have a record keeping system for an organisation with a hierarchical structure of offices (units) - national → state → regional → local and uses the Tree behaviour

A user is assigned to a particular unit and they can interact with that unit and those “under” the unit using the “lft” & “rght” - in the CakePHP2 app we had a simple behaviour “UnitAuthorise” on each relevant Model that would check the user and “Unit” they were interacting with - all very simple and worked for Associated models - a member might be assigned to a “Unit” and if you were authorised to interact with that Unit, you could also interact with that member’d record.

In CakePHP4 I’ve learnt I can’t access the logged in user from within a Behaviour or at the Model level, and was recommended to use authorisations and create Policies.

I’ve created some policies but it is quite repetitive, each policy had multiple entries, for “canEdit”, “canView” etc

        // Get User's highest Unit they can access
        $highest_unit = $user->active_user_unit->unit;

        if ($unit->lft >= $highest_unit->lft && $unit->rght <= $highest_unit->rght){
            return true;
        } else {
            return false;
        }

So I’ve put these in a BeforePolicyInterface so as not to repeat myself.

Is this the best way?

Also, how do I create a policy for adding a record? If I’m adding a record (eg a note) against a unit, there be an “Add” action on the “UnitNote” controller with the ID of the unit the record is associated against

/unit-notes/add/6

But I don’t have the Unit info for the add action - I need to access the param somehow to check the user is authorised for the Unit. The way I’ve created it so far, the user could edit the URL

/unit-notes/add/2

and add a note against a Unit they are not authorised for.

It’s probably staring me in the face but I’ve been scratching my head all afternoon thinking about this :frowning:

Thanks in advance

Ok, thinking about this a bit more and I think I got it.

As it’s an “add”, I need to authorise against the Unit and no the non-existent UnitNote

So in my controller I have

   public function add($id = null)
    {
        $unit = $this->UnitNotes->Units->get($id);

        // Check authorisation policy
        $this->Authorization->authorize($unit, 'addUnitNote');

        $unitNote = $this->UnitNotes->newEmptyEntity();

And in my UnitPolicy I have

    public function canAddUnitNote(IdentityInterface $user, Unit $unit)
    {
        // Get User's highest Unit
        $highest_unit = $user->active_user_unit->unit;

        if ($unit->lft >= $highest_unit->lft && $unit->rght <= $highest_unit->rght){
            return true;
        } else {
            return false;
        }
    }