2009-01-23 9 views
0

Imaginez que j'ai 4 tables de base de données et une interface qui présente des formulaires pour la gestion des données dans chacun de ces tableaux sur une seule page Web (en utilisant le motif de conception d'accordéon pour montrer seulement une forme à la fois). Chaque formulaire est affiché avec une liste de lignes dans le tableau, permettant à l'utilisateur d'insérer une nouvelle ligne ou de sélectionner une ligne à éditer ou à supprimer. AJAX est ensuite utilisé pour envoyer la requête au serveur.Zend Framework: comment afficher plusieurs actions, chacune nécessitant des niveaux d'autorisation différents, sur une seule page

Un ensemble de formulaires différent doit être affiché pour différents utilisateurs, en fonction de l'ACL de l'application.

Ma question est la suivante: En termes de contrôleurs, d'actions, de vues et de mises en page, quelle est la meilleure architecture pour cette interface? Par exemple, jusqu'à présent, j'ai un contrôleur avec ajouter, modifier et supprimer des actions pour chaque table. Il y a une indexAction pour chacun, mais c'est une fonction vide. J'ai également étendu Zend_Form pour chaque table. Pour afficher les formulaires, je puis dans l'IndexController passer la forme à sa vue, et l'écho de chaque formulaire. Javascript prend ensuite soin de remplir le formulaire et d'envoyer des requêtes à l'action add/edit/delete appropriée du contrôleur approprié. Cela ne permet cependant pas à ACL de contrôler l'affichage ou non des formulaires pour différents utilisateurs.

Serait-il préférable que indexAction instancie le formulaire, puis utilise quelque chose comme $ this-> render(); rendre chaque vue dans la vue de l'indexAction de l'IndexController? L'ACL empêcherait-il certaines vues d'être rendues?

Cheers.

Répondre

1

Il y a quelques endroits que vous pouvez exécuter vos contrôles contre votre ACL:

  1. où vous avez votre boucle (ou bloc hardcoded) pour charger chaque forme.
  2. Dans le constructeur de chacun des objets de formulaire, peut-être lancer une exception personnalisée, qui peut être interceptée et traitée de manière appropriée.
  3. À partir du constructeur d'une extension de Zend_Form à partir de laquelle tous vos objets formulaire personnalisés sont étendus (probablement la meilleure méthode, car elle permet de réduire la duplication de code).

Gardez à l'esprit que si vous utilisez ZF pour effectuer une solution AJAXy pour votre mise à jour, votre contrôleur doit exécuter la vérification des ACL dans sa méthode init() ainsi, empêcher les modifications non autorisées à votre base de données.

Espérons que ça aide.

-1

J'utilise une version modifiée de ce qui est dans le livre "Zend Framework in Action" de Manning Press (disponible en téléchargement PDF si vous en avez besoin maintenant). Je pense que vous pouvez simplement télécharger le code d'accompagnement à partir du site du livre. Vous voulez regarder le code du chapitre 7.

Vue d'ensemble:

Le contrôleur est la ressource, et l'action est le privilège. Mettez votre permet & denys dans la méthode init du contrôleur. J'utilise également une version personnalisée de leur Controller_Action_Helper_Acl.

Chaque contrôleur a une méthode getAcls public static:

public static function getAcls($actionName) 
{ 
    $acls = array(); 
    $acls['roles']  = array('guest'); 
    $acls['privileges'] = array('index','list','view'); 

    return $acls; 
} 

Cela permet à d'autres contrôleurs posent des questions sur les autorisations de ce contrôleur. Chaque méthode d'initialisation du contrôleur appelle $ this -> _ initAcls(), qui est défini dans mon propre contrôleur de base:

public function init() 
{ 
    parent::init(); // sets up ACLs 
} 

Le parent ressemble à ceci:

public function init() 
{ 
    $this->_initAcls(); // init access control lists. 
} 

protected function _initAcls() 
{ 
    $to_call = array(get_class($this), 'getAcls'); 
    $acls = call_user_func($to_call, $this->getRequest()->getActionName()); 
    // i.e. PageController::getAcls($this->getRequest()->getActionName()); 

    if(isset($acls['roles']) && is_array($acls['roles'])) 
    { 
     if(count($acls['roles'])==0)  { $acls['roles'] = null; } 
     if(count($acls['privileges'])==0){ $acls['privileges'] = null; } 
     $this->_helper->acl->allow($acls['roles'], $acls['privileges']); 
    } 
} 

Je viens d'une fonction appelée :

aclink($link_text, $link_url, $module, $resource, $privilege); 

Il appelle {$ resource} Controller :: getAcls() et effectue des vérifications d'autorisations à leur encontre. Si elles ont l'autorisation, il renvoie le lien, sinon il renvoie ''.

function aclink($link_text, $link_url, $module, $resource, $privilege) 
{ 
    $auth = Zend_Auth::getInstance(); 

    $acl = new Acl(); //wrapper for Zend_Acl 
    if(!$acl->has($resource)) 
    { 
     $acl->add(new Zend_Acl_Resource($resource)); 
    } 

    require_once ROOT.'/application/'.$module.'/controllers/'.ucwords($resource).'Controller.php'; 

    $to_call = array(ucwords($resource).'Controller', 'getAcls'); 
    $acls = call_user_func($to_call, $privilege); 

    if(isset($acls['roles']) && is_array($acls['roles'])) 
    { 
     if(count($acls['roles'])==0)  { $acls['roles'] = null; } 
     if(count($acls['privileges'])==0){ $acls['privileges'] = null; } 
     $acl->allow($acls['roles'], $resource, $acls['privileges']); 
    } 

    $result = $acl->isAllowed($auth, $resource, $privilege); 

    if($result) 
    { 
     return '<a href="'.$link_url.'" class="aclink">'.$link_text.'</a>'; 
    } 
    else 
    { 
     return ''; 
    } 
} 
0

Avez-vous déjà résolu celui-ci?

Je construis une grande application de base de données avec beaucoup de sous-contrôleurs imbriqués en tant que panneaux sur un tableau de bord montré sur le contrôleur parent. code source est simplifié ci-dessous: vient de mon parentController-> indexAction()

$dashboardControllers = $this->_helper->model('User')->getVisibleControllers(); 
    foreach (array_reverse($dashboardControllers) as $controllerName) // lifo stack so put them on last first 
    { 
     if ($controllerName == 'header') continue; // always added last 
     // if you are wondering why a panel doesn't appear here even though the indexAction is called: it is probably because the panel is redirecting (eg if access denied). The view doesn't render on a redirect/forward 
     $this->_helper->actionStack('index', $this->parentControllerName . '_' . $controllerName); 
    } 
    $this->_helper->actionStack('index', $this->parentControllerName . '_header'); 

Si vous avez une meilleure solution, je serais désireux de l'entendre. Pour ma prochaine astuce, je dois comprendre comment les afficher dans une, deux ou trois colonnes en fonction d'un paramètre de préférence de l'utilisateur