CakePHP mit Access Listen beschleunigen

13 03 2008

Ich habe mich heute wieder ein stück mit CakePHP beschäftig, da ich dieses für ein Projekt benötige.

Da ich gleich alles richtig machen wollte, habe ich mir das ACL Modul von Cake vorgenommen um meine anwendung gleich tauglich für Benutzergruppen zu machen. Dabei ist mir aber etwas unschönes aufgefallen. Cake fragt die Informationen immer wieder ab, wenn man diese nicht zwischenspeichert. Das kostet einfach massive viele SQL Queries die unnötig sind (ausser man braucht wirklich eine anwendung, wo sich alle paar minuten die Benutzerrechte ändern). Aus diesem Grund habe ich ein kleine erweiterung für den AppController geschrieben, die sicherlich für viele nützlich sein könnte.

Damit werden einfach alle Variablen in der Session zwischengespeichert. Sinnvoll wäre noch eine Erweiterung um einen statisch Klassenvariable, damit die werte nicht immer wieder (bei Nutzung mehrerer Classen die Instanzen vom AppController sind) mit dem Session wert Überschrieben werden. Spart wieder ein paar Prozessortzyklen.

Diese Funktion speichert die Access Controll Objects (ACO) in Variablen für den View, wobei jeweils ein „m_“ + Aco Name genutzt wird.

function defineRights(){
$todo = array('orders', 'uploads', 'packages', 'artnotranslates', 'articelgroups');

if($this->Session->check('User') && (true != $this->Session->read('Rights'))){

foreach($todo AS $task)

$this->writeToSession($task);

$this->Session->write('Rights', true);

}

$this->set('user', $this->Session->read('User'));

foreach($todo as $task)

$this->set('m_'.$task, $this->Session->read($task));

}

Diese Funktion schreibt alle möglichkeiten von Cake ACL’s in ein Hash. Man kann dann mit $m_ACONAME[‚read‘] z.B. das Leserecht im „view“ erfragen.

function writeToSession($rule = null){
if($rule != null){

$this->Session->del($rule);

$dummy = array(

'any' =>        $this->checkBAccess($rule),

'read' =>       $this->checkBAccess($rule, 'read'),

'create'=>      $this->checkBAccess($rule, 'create'),

'update'=>      $this->checkBAccess($rule, 'update'),

'delete'=>      $this->checkBAccess($rule, 'delete')

);

$this->Session->write($rule, $dummy);

}

}

Grundlage dafür ist die check Funktion von Cake. Theoretisch könnte man diese Methode auch verkürzen indem man den Rückgabewert von check direkt als return wert nimmt.

function checkBAccess($aco, $action='*'){
$user = $this->Session->read('User');

$access= $this->Acl->check($user['username'] , $aco, $action);

if($access === false)

return false;

else

return true;

}

So wäre auch wieder etwas mehr Sicherheit und Flexibilität für den Entsprechenden Designer der sich mit dem Design beschäftigen darf. Man sollte aber erwähnen, dass trotzdem eine Überprüfung im Controller für sichere Programmierung unerlässlich ist. Alternativ wäre ein zusammenspiel aus diesen Funktionen und $this->action möglich, jedoch wäre dann eine vollständige Auflistung aller Funktionen und nötig.

Die Funktion lasst ihr am besten per var $beforeFilter = array(‚defineRights‘); aufrunfen.

Advertisements