When I log in to my application, the user information and permissions are stored in the session’s authentication object.
My User Entity implements the IdentityInterface.
However, if the user itself or an administrator changes the information in the database, this object should be updated in the session.
As a temporary measure, I ran the following command while editing in UserController:
public function edit($id=null) {
...
$this->refreshSessionData();
...
}
private function refreshSessionData()
{
$user = $this->Users->get($this->Authentication->getIdentity()->get('id'), ['finder' => 'authenticatedUser']);
$this->Authentication->setIdentity($user);
}
However, I now had the problem that this only applied to one session, so if I was logged in in another browser with the same user, that data in session was not updated.
Now my approach is to fetch the user data from the database with every request and update the session. I wanted to do this via the AppController::beforeFilter(), but it doesn’t seem to work.
public function beforeFilter(EventInterface $event)
{
parent::beforeFilter($event);
$user = $this->fetchTable('Users')->get($this->Authentication->getIdentity()->get('id'), ['finder' => 'authenticatedUser']);
$this->Authentication->setIdentity($user);
}
I get the following error message.
Call to undefined method App\Model\Entity\User::can()
in RequestAuthorizationMiddleware…
Sorry, i did this in AppController’s beforeFilter() method, but that didn’t work, because after that many other components or in view it’s expecting an Authorization/Identity type, but there was a Entity/User type and it couldn’t find the can() method.
Please see my first post.
In UsersController → refreshSessionData() the setIdentity() works well. When i move that to beforeFilter() in AppController it doesn’t work. Maybe because i redirect to another page after set the Identity in UsersController?
If you use the CakeDC/Users plugin, then you can use the AuthLinkHelper that generates an action link only, if the permissions (in the config/permissions.php file) are defined.
<?= $this->AuthLink->link('Users', '/users') ?>
But true, it is a bit complicated to get a good workflow for setting possible actions for a user and then outputting in the view. Because I find, that permissions logic has nothing to do with the view. Instead I implemented some classes (traits, policies, helpers, etc.) where then a controllers beforeRender() method is invoked to get the possible actions for a certain view or entity. This actions are set to the view and then the helper creates me the appropriate action links.
However, I now had the problem that this only applied to one session, so if I was logged in in another browser with the same user, that data in session was not updated.
Each browser will have it’s own session record so obviously updating the session info in one browser won’t affect the session in another browser.
To achieve what you want you’ll have to use db based sessions and then search for all records matching the required user id and update them directly in db.
Or else don’t store those details in the session. Perhaps server-side cache with the user ID as the key would be better for this use case, for example.
The identify option fetches the current user information from the database and stores it in the request’s identity attribute. It does not refresh the session!
So when the user changes their password in session no. 1, the same user logged out in session no. 2. That’s also exactly what I want.