Fake caching CakePHP permitted actions

See an update here: Real-caching CakePHP permitted actions

In my previously posted CakePHP component/helper pair (and more) that displays links in views depending upon ACL permissions, I've added a fake caching system for storing permissions. I call it "fake" caching because I'm not using Cake's cache system at all. Rather, I'm "caching" the user's ACL-permitted actions in his session. Whenever the session is regenerated, the fake cache will be, also. It will also allow forcing of a refresh of the list. First up, here's the code that I drop into app_controller.php:

	/**
	 * "Fake caching" of permitted controller/action pairs into the user's session.
	 *
	 * @param bool $refresh Set to true to force refresh of permitted controller/action pairs.
	 */
	function _sessioncachePerms($refresh = false)
	{
		//$refresh=true;
		$uid = $this->Auth->user('id');
		if ($refresh && $uid)
		{
			$this->Session->delete('Auth.AclPermsUser'.$uid);
		}
		$isCacheSet = $this->Session->read('Auth.AclPermsUser'.$uid);
		if ($this->Auth && $this->Acl && $uid && empty($isCacheSet))
		{
			// group perms
			$pArr = array();
			$allPerms = $this->Acl->Aro->find('threaded', array('conditions' => array('Aro.foreign_key' => $this->Auth->user('group_id'))));
			foreach ($allPerms[0]['Aco'] as $action)
			{
				$pArr[] = $this->Acl->Aco->getpath($action['id']);
			}
			$perms = array();
			$permsCounter = 0;
			foreach ($pArr as $permStruct)
			{
				$perms[$permsCounter] = '';
				foreach ($permStruct as $permChunk)
				{
					$perms[$permsCounter] .= $permChunk['Aco']['alias'] .'/';
				}
				$perms[$permsCounter] = rtrim($perms[$permsCounter], '/');
				if (!$this->Acl->check(array('model' => 'User', 'foreign_key' => $this->Auth->user('id')), $perms[$permsCounter]))
				{
					unset($perms[$permsCounter]);
				}
				$permsCounter++;
			}
			// $perms contains permitted ACOs, but not Auth->allowedActions
			//debug($perms);

			// user perms
			$pArr = array();
			//$allPerms = $this->Acl->Aro->find('threaded', array('conditions' => array('Aro.foreign_key' => $this->Auth->user('group_id'))));
			//debug($allPerms);
			foreach ($allPerms[0]['children'][0]['Aco'] as $action)
			{
				$pArr[] = $this->Acl->Aco->getpath($action['id']);
			}
			foreach ($pArr as $permStruct)
			{
				$perms[$permsCounter] = '';
				foreach ($permStruct as $permChunk)
				{
					$perms[$permsCounter] .= $permChunk['Aco']['alias'] .'/';
				}
				$perms[$permsCounter] = rtrim($perms[$permsCounter], '/');
				if (!$this->Acl->check(array('model' => 'User', 'foreign_key' => $this->Auth->user('id')), $perms[$permsCounter]))
				{
					unset($perms[$permsCounter]);
				}
				$permsCounter++;
			}
			// $perms contains permitted ACOs, but not Auth->allowedActions
			//debug($perms);
			$this->Session->write('Auth.AclPermsUser'.$uid, $perms);
		}
	}

And then I add

$this->_sessioncachePerms();
in AppController's beforeFilter() after the Auth setup. The only other placed I've used it in the sandbox is after changing permissions on an ARO. Then it's necessary to use
$this->_sessioncachePerms(true);
to force a rebuild of the "cache".

Instead of templatizing my previous work to permit operation with either constant ACL checks or this fake caching, I just changed the AclPermittedActions component to work only with this. I might get around to making a generic system in the future, but I don't have the need or the time right now. I'll attach the modified component to this post.

I should note that this arrangement will not work with a controller's Auth->allowedActions. That can be implemented, but it would require quite a bit of overhead on the initial cache build because it would require using something like a controller list and a series of App::import()s, I think. It's something that would be good to have, but the main app I'm working on will have permissions on every action set through ACL allow/deny rather than allowedActions. That wouldn't work so well for an open website, but it's necessary for this project.

AttachmentSize
acl_permitted_actions.php_.txt4.63 KB

freetags:

Add new comment