Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [ZendFramework] Zend_Acl
Forum PHP.pl > Forum > PHP > Frameworki
nexis
W jaki sposób mogę w widoku (np. views/scripts/index/index.phtml) uzyskać informację czy zalogowany użytkownik ma dostęp do jakiegoś działu? Chciałbym to uzyskać za pomocą funkcji typu isAllowed('controller', 'action') abym mógł ukryć linki w menu, do których użytkownik tak czy inaczej nie ma dostępu. Zend_Acl skonfigurowałem w następujący sposób:

bootstrap.php
  1. <?php
  2. defined('APPLICATION_PATH')
  3.   or define('APPLICATION_PATH', dirname(__FILE__));
  4.  
  5. defined('APPLICATION_ENVIRONMENT')
  6.    or define('APPLICATION_ENVIRONMENT', 'development');
  7.  
  8. $frontController = Zend_Controller_Front::getInstance();
  9. $frontController->setControllerDirectory(APPLICATION_PATH . '/controllers');
  10. $frontController->setParam('env', APPLICATION_ENVIRONMENT);
  11.  
  12. Zend_Layout::startMvc(APPLICATION_PATH . '/layouts/scripts');
  13. $view = Zend_Layout::getMvcInstance()->getView();
  14. $view->doctype('XHTML1_STRICT');
  15.  
  16. $configuration = new Zend_Config_Ini(APPLICATION_PATH . '/config/app.ini', APPLICATION_ENVIRONMENT);
  17.  
  18. $dbAdapter = Zend_Db::factory($configuration->database);
  19. $dbAdapter->query('SET NAMES utf8');
  20. Zend_Db_Table_Abstract::setDefaultAdapter($dbAdapter);
  21.  
  22. $registry = Zend_Registry::getInstance();
  23. $registry->configuration = $configuration;
  24. $registry->dbAdapter     = $dbAdapter;
  25.  
  26. require_once APPLICATION_PATH . '/models/Acl.php';
  27. require_once APPLICATION_PATH . '/models/Auth.php';
  28. $auth = Zend_Auth::getInstance();
  29. $acl  = new Acl($auth);
  30. $frontController->registerPlugin(new Auth($auth, $acl))
  31.                ->setParam('auth', $auth);
  32.  
  33.  
  34. unset($frontController, $view, $configuration, $dbAdapter, $registry);
  35. ?>


models/Auth.php
  1. <?php
  2. class Auth extends Zend_Controller_Plugin_Abstract
  3. {
  4.   public $_auth;
  5.   public $_acl;
  6.  
  7.   private $_noauth = array('module' => 'default', 'controller' => 'user', 'action' => 'login');
  8.   private $_noacl  = array('module' => 'default', 'controller' => 'user', 'action' => 'noAccess');
  9.  
  10.   public function __construct($auth, $acl)
  11.   {
  12.      $this->_auth = $auth;
  13.      $this->_acl  = $acl;
  14.   }
  15.   public function preDispatch(Zend_Controller_Request_Abstract $request)
  16.   {
  17.      $role = ($this->_auth->hasIdentity()) ? $this->_auth->getStorage()->read()->role : 'guest';
  18.  
  19.      $controller = $request->controller;
  20.      $action     = $request->action;
  21.      $module     = $request->module;
  22.      $resource   = $controller;
  23.  
  24.      if (!$this->_acl->has($resource)) {
  25.         $resource = null;
  26.      }
  27.  
  28.      if (!$this->_acl->isAllowed($role, $resource, $action)) {
  29.         if (!$this->_auth->hasIdentity()) {
  30.            $module     = $this->_noauth['module'];
  31.            $controller = $this->_noauth['controller'];
  32.            $action     = $this->_noauth['action'];
  33.         } else {
  34.            $module     = $this->_noacl['module'];
  35.            $controller = $this->_noacl['controller'];
  36.            $action     = $this->_noacl['action'];
  37.         }
  38.      }
  39.        
  40.      $request->setModuleName($module);
  41.      $request->setControllerName($controller);
  42.      $request->setActionName($action);
  43.   }
  44. }
  45. ?>


models/Acl.php
  1. <?php
  2. class Acl extends Zend_Acl
  3. {
  4.   public function __construct(Zend_Auth $auth)
  5.   {      
  6.      $this->add(new Zend_Acl_Resource('category'));
  7.      $this->add(new Zend_Acl_Resource('error'));
  8.      $this->add(new Zend_Acl_Resource('index'));
  9.      $this->add(new Zend_Acl_Resource('localization'));
  10.      $this->add(new Zend_Acl_Resource('object'));
  11.      $this->add(new Zend_Acl_Resource('objectcategory'));
  12.      $this->add(new Zend_Acl_Resource('objectelement'));
  13.      $this->add(new Zend_Acl_Resource('objectphoto'));
  14.      $this->add(new Zend_Acl_Resource('pattern'));
  15.      $this->add(new Zend_Acl_Resource('patternelement'));
  16.      $this->add(new Zend_Acl_Resource('postcode'));
  17.      $this->add(new Zend_Acl_Resource('user'));
  18.      
  19.      # Guest
  20.      $this->addRole(new Zend_Acl_Role('guest'));
  21.      $this->allow('guest', 'index');
  22.      $this->allow('guest', 'error');
  23.      $this->allow('guest', 'user');
  24.      
  25.      # Editor
  26.      $this->addRole(new Zend_Acl_Role('editor'), 'guest');
  27.      $this->allow('editor', 'localization');
  28.      $this->allow('editor', 'object');
  29.      $this->allow('editor', 'objectcategory');
  30.      $this->allow('editor', 'objectelement');
  31.      $this->allow('editor', 'objectphoto');
  32.      $this->allow('editor', 'postcode');
  33.      
  34.      # Manager
  35.      $this->addRole(new Zend_Acl_Role('manager'), 'editor');
  36.      $this->allow('manager', 'category');
  37.      $this->deny('manager', 'object', 'activate');
  38.      $this->allow('manager', 'pattern');
  39.      $this->allow('manager', 'patternelement');
  40.      
  41.      # Administrator
  42.      $this->addRole(new Zend_Acl_Role('administrator'));
  43.      $this->allow('administrator');
  44.   }
  45. }
  46. ?>
qba_rox
utworz sobie view helper, ktory renderuje ci menu i w nim pobierz z rejestru obiekt acl i sprawdzaj dostep do danego linku. chyba o to chodzi? smile.gif

jest pozno i tak sobie wymyslilem: tongue.gif
  1. <?php
  2. class Your_View_Helper_RenderMenu {
  3.  
  4.    public function RenderMenu() {
  5.        
  6.        $acl = Zend_Registry::get('acl');
  7.                $role = Your_Auth->getInstance()->getRole();
  8.  
  9.                if($acl->isAllowed($role, 'menu1', 'display')){
  10.                   $menu .= '<a>menu1</a>';
  11.                }
  12.    }
  13. //...
  14.  
  15. }
  16. ?>

o to chodzilo? smile.gif
batman
A ja dodam od siebie, że ten helper powinien rozszerzać helper url i zwracać albo pusty ciąg (jeśli użytkownik nie ma uprawnień) lub to co zwraca helper url (jeśli użytkownik posiada uprawnienia).
LBO
Cytat(batman @ 16.01.2009, 09:42:51 ) *
A ja dodam od siebie, że ten helper powinien rozszerzać helper url i zwracać albo pusty ciąg (jeśli użytkownik nie ma uprawnień) lub to co zwraca helper url (jeśli użytkownik posiada uprawnienia).


Nie zgodzę sie z Tobą - to niepotrzebne mieszanie odpowiedzialności. Spójrz na poniższe podejście:

  1. <?php if($this->acl()->isAllowed($this->auth()->getRole(), 'menu1', 'display')) : ?>
  2. <div><?php print $this->menu(); ?></div>
  3. <?php else : ?>
  4. <div>menu niedostępne</div>
  5. <?php endif; ?>


Posiadasz większą kontrolę. Dodatkowo przy tym sposobie nie musisz się ograniczać do menu, ale także do pojedynczych linków tj. "edytuj", "usuń"; które prowadza do akcji wymagających pewnych uprawnień.

Ważne, żeby posiadać helpery wykonujące jak najbardziej "atomowy" kod. Dzięki temu możesz tworzyć i proste jak i bardzo skomplikowane struktury.
batman
Cytat(LBO @ 16.01.2009, 11:29:48 ) *
Nie zgodzę sie z Tobą - to niepotrzebne mieszanie odpowiedzialności. Spójrz na poniższe podejście:

Dlaczego?
Jeśli chcesz zrobić link, który ma się wyświetlać tylko dla konkretnej grupy użytkowników nie musisz kombinować z if-ami, które zaciemniają kod. Po prostu używasz helpera i nie martwisz się o to, czy dany element menu ma się pokazać, czy nie. A jeśli nie chcesz rozszerzać helpera url, to możesz po prostu go zastosować wewnątrz swojego helpera.
LBO
Przesadzasz z tymi ifami to właśnie bez Nich jest mniej czytelnie.

  1. <?php
  2. $this->menu();
  3. ?>


To mi nic nie mówi. Czy się będzie wyświetlać i kiedy.
batman
To dodaj do przykładu jeszcze z 10 linków i każdy trzymaj w takim if-ie. Od razu można się pogubić. Poza tym wszystkie zmiany w uprawnieniach powodują, że trzeba w każdym if-ie zmieniać warunek. A tak, wystarczy zmienić to w jednym miejscu - w helperze.
LBO
Linki linkami. Natomiast taki sposób jaki ty podajesz powoduje, że przeładowujesz helper funkcjonalnością - menu() wyświetla menu i tyle. Ty chcesz jeszcze wpakować odpowiedzialność czy w ogóle ma je wyświetlać.

Nie twierdzę, że mam robić drzewko ifów tylko, że w budowie samych helperów trzeba zachować umiar. ot co.
batman
Nie do końca pisaliśmy o tym samym. Ty pisałeś o całym menu, a ja o konkretnych linkach. Dlatego nie możemy dojść do porozumienia. Jeśli autor stworzy helper, który wyświetli lub nie (w zależności od uprawnień) elementy menu (linki), wówczas osiągnie to o co mu chodziło.
LBO
Zawsze są jeszcze partiale. Nie wymagają dodatkowego helpera i posiadają korzyści płynące z mojego sposobu.
qba_rox
Rozbijanie problemu wyswietlania linkow, na pojedyncze helpery nie ma zadnego sensu, bo jest to nie wydajne (zobacz ile obiektow musisz powolac i wykonywac wielokrotnie czynnosci ktore mozna zrobic raz) i robi bajzel w pliku widoku.
uwazam tak jak LBO, ze $this->renderMenu() jest duzo lepszym sposobem. Choc wcale nie zgodze sie z tym, ze sprawdzamy dostep tylko do calego menu.
Cytat
Poza tym wszystkie zmiany w uprawnieniach powodują, że trzeba w każdym if-ie zmieniać warunek. A tak, wystarczy zmienić to w jednym miejscu - w helperze.

nie prawda:
  1. <?php
  2. $menu['add'] = 'Dodaj';
  3. $menu['edit'] = 'Edytuj';
  4. $menu['delete'] = 'Usun';
  5.  
  6. //lub $menu = $model->getMenu();
  7. $menu = '';
  8. foreach($menu as $key=>$entry){
  9.  if($acl->isAllowed($role, "mainMenu:$key", 'display'))
  10.    $menu .= "<a>$entry</a>" . PHP_EOL;
  11.  
  12. }
  13.  
  14. return $menu;
  15. ?>

gdzie sa ify? bo ja ich nie widze tongue.gif i mamy tylko jedna instrukcje sprawdzania uprawnien smile.gif
batman
No tak, ale cały czas kręcimy się w obrębie menu. A co jeśli trzeba stworzyć osobne linki, np edycja. Wówczas dla każdego linka trzeba będzie tworzyć helper. A o wydajność się nie martwię z dwóch powodów.
1. Jeśli stawiam aplikację na ZF, to jest to aplikacja kombajn, a nie wizytówka.
2. Wszystko co tylko można jest cache-owane.
qba_rox
Hehe, mysle ze koles co zalozyl temat, ma juz odpowiedz biggrin.gif
masz racje, czasem warto poswiecic wydajnosc na rzecz lepszej swobody w programowaniu skoro i tak to cachujemy smile.gif uwazam ze twoje podejscie jest bardzo dobre jesli chodzi o o pojedyncze linki, ale uwazam ze moje jest lepsze jesli mowimy o zbiorze linkow luzno powiazanych z soba (np menu). Co szkodzi nam miec 2 helpery, do pojedynczow liknkow jak i do ich grupy? tongue.gif
LBO
Nie narzekajcie z tymi obiektami helperów, bo te są tworzone tylko raz smile.gif Przynajmniej byływ czasach ~1.0 smile.gif Poprawcie mnie jeżeli się mylę, bo do ZF dawno nie zaglądałem.
batman
Dokładnie o to mi chodziło. Nie ma przecież obowiązku korzystać za każdym razem z helpera, który sprawdza prawa dostępu. Przecież nie każdy link prowadzi do strony z ograniczeniami.
Poza tym jeśli chodziłoby o menu, to też bym zrobił osobny helper do tego.


Zapomniałem dodać po pierwszego punktu w poprzednim moim poście, że taka aplikacja stoi na potężnej maszynie, której nie straszny jest ZF winksmiley.jpg


edit up
Tak. Obiekt helpera jest tworzony tylko raz.
qba_rox
to prawda raz, ale nie chodzilo mi tu akurat o same obiekty helperow, tylko obiekty wewnatrz helpera, np obiekt modelu, konfiguracji (oczywiscie moze nie byc zadnych obiektow), poza tym odwolywanie sie dziesiatki razy do helpera nie jest wydajne, po to ludzie robia cos takiego.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.