Accessing Logged in User in Model

Hi all

What is the ‘best/correct’ way to access the logged in user in a custom finder?

I’m porting some logic from CakePHP2 to CakePHP4 and we used to have a custom finder list that provides a list of Units that a user can access

With the old Auth Component it was a simple matter to access the AuthComponent in the model

$highestUnitId = AuthComponent::user('highest_unit_id');

In the CakePHP4 with the Authentication plugin we don’t get access to the logged in user details

Keen to keep code as simple as possible - how should this be handled? Do I need to pass the Identity in the custom finder? Is there some other preferred way?

I can’t say this is the correct way, so if not hopefully we’ll get corrected - but this is my approach.
In /src/AppController.php in public function beforeFilter(\Cake\Event\EventInterface $event) : -

    public function beforeFilter(\Cake\Event\EventInterface $event)
    {
        parent::beforeFilter($event);
...
        $data = $this->Authentication->getResult()->getData(); //user entity, null when not logged in
        $this->isLoggedIn = $this->Authentication->getResult()->isValid();
        $this->loggedInID = $this->isLoggedIn ? $data->id : -1;
        $this->loggedInEmail = $this->isLoggedIn ? h($data->email) : "";
        $this->loggedInFullname = $this->isLoggedIn ? h($data->fullname) : ""; // h() to sanitise
        $this->adminLevel = $this->isLoggedIn ? $data->adminlevel : -1;
        $this->set(['isLoggedIn' => $this->isLoggedIn,
                    'loggedInID' => $this->loggedInID,
                    'loggedInEmail' => $this->loggedInEmail,
                    'loggedInFullname' => $this->loggedInFullname,
                    'adminLevel' => $this->adminLevel
                  ]);       
}

Where loggedInFullname & adminLevel are extra fields in my Users table.

What this allows is all these fields will be available in all controllers via $this-> and they are also available in all templates via the set()

Maybe that can help.

Check out GitHub - UseMuffin/Footprint: CakePHP plugin to allow passing currently logged in user to model layer.

@Jawfin thanks - unfortunately I’m looking for a way to access in the Model, not the Controller or Templates.

I have a custom finder in the Table but I need to pass the user in $options from the controller to be available

public function findListAuthorised(Query $query, array $options)
{
    $user = $options['user'];
    $unit = $this->_getAuthorisedUnit($user);

    return $query
        ->find('list')
        ->contain('ParentUnits')
        ->where([
            'ParentUnits.lft >=' => $unit['lft'],
            'ParentUnits.rght <=' => $unit['rght'],
        ]);
}

It would be great if I didn’t need to pass $options from the “controller” in every find

@Zuluru I’m using Footprint to save the logged in user, from “_footprint” in $options, but not sure how that can be available beyond the events with save etc.

I would probably just pass the data you need via the Finder Options. However, the Identity should be already be part of the Request.

Perhaps in the Controller you can debug to double check:

/** @var \Authorization\Identity $identity */
$identity = $this->getRequest()->getAttribute('identity');
debug($identity->getOriginalData());

If that is the case, what I have done previously is just create a reusable Trait to add a protected method to obtain what I need via the Cake\Routing\Router Class in the Model.

1 Like

The Footprint plugin injects itself into the various model event handlers, adding a “_footprint” (by default, it can be changed in the configuration) key into the options, with the identity as the value, which other listeners (e.g. beforeSave) can access. See the “Trait” section of the “Usage” part of the manual.

1 Like

In 3.1 with cakedc users (but probably not only)

use Cake\Network\Session;
...
$user_id = (new Session())->read('Auth.User.id');

from my working code.