Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [ZendFramework]Warunkowy ACL
Forum PHP.pl > Forum > PHP > Frameworki
mrok
Pracuję nad systemem do zarządzania firmą, który nie będzie sprzedawany w pudełku, ale każdy chętny będzie sobie mógł założyć konto i w obrębie jego pracować (dostęp przez www).

Implikuje to nałożenie ograniczeń do zasobów, tak aby user z firmy X nie mógł przeglądać dokumentów z firmy Y.

Dotychczas poprzednicy napisali w tym celu sporo metod rozrzuconych po modelach i kontrolerach - ogólnie lekki burdel.

Chciałbym trochę tego posprzątać i tę logikę przenieść do "warunkowych ACLi"

np
  1. $acl = new Zend_Acl();
  2. $acl->allow('owner', 'document:list', 'show', new CompanyAssertion());


Czy ktoś podziela taki pomysł (może powinienem zrobić ankietę)? Podobno poprzednicy to byli prawdziwi ninja i zastanawiam się czy przypadkiem nie próbuję wynaleźć koła na nowo.
Spawnm
Do tego acl raczej nie będzie potrzebny.
Jeśli wszystko jest oparte o bazę danych to sprawdzaj czy user należy do danej firmy jeśli tak może przeglądać i pobierać dane.
A ACL daj aby ustalić co konkretnie może przeglądać no i czy może dodawać, edytować, kasować.
mrok
Cytat
Jeśli wszystko jest oparte o bazę danych to sprawdzaj czy user należy do danej firmy jeśli tak może przeglądać i pobierać dane.

Oto właśnie chciałem zapytać - gdzie najlepiej to sprawdzić?

Przecież user może sobie spokojnie zmienić w linku
www.blebleble.pl/x/y/z/doc_id/7 na np www.blebleble.pl/x/y/z/doc_id/8

ACL wg Ciebie powinien to puścić ponieważ user ma prawo do przeglądania, edycji, etc. dokumentów

Teraz w modelu dokumentu należałoby dodać jakieś metody które sprawdzają czy user może przeglądać, edytować, usuwać, wysyłać etc.
Mnóstwo sprawdzania zależnego od kontekstu usera, na dodatek trzeba by taką metodę (canEdit, canDelete) wywoływać ręcznie i tu każdy może sie pomylić (albo co gorsza zapomnieć).

Nie ma ciekawszych rozwiązań? Niekoniecznie opartych o ACLe
destroyerr
Problem spory i zależy od reszty architektury systemu.
Ogólnie: kontroler powinien zapytać model czy dany użytkownik może wykonać jakąś operację. Więc model powinien mieć interfejs udostępniający możliwość sprawdzenia tego dostępu i to jest chyba jasne. Natomiast najważniejsza kwestia jak model powinien sprawdzać czy jest dostęp. Próbowałem stworzyć podobny system do Twojego (niestety bardziej rozbudowany) i chyba się udało, więc Zend_ACL się nadaje. Ma moim zdaniem jest w nim parę niekonsekwencji (ale to moja interpretacja).
Zdecydowanie dla użytkowników i np. dokumentów nie tworzyłbym tekstowych ról i zasobów tylko skorzystałbym z Zend_Acl_Role_Interface i Zend_Acl_Resource_Interface. Wtedy w CompanyAssertion dostajesz do sprawdzenia obiekt użytkownika i obiekt zasobu dzięki czemu sprawnie możesz pobrać od użytkownika i dokumentu firmę i wtedy porównać. Czyli coś takiego:
  1. class User implements Zend_Acl_Role_Interface
  2. {
  3. public function getRoleId()
  4. {
  5. return sprintf('user:%s', $this->getId());
  6. }
  7. }
  8.  
  9. class Document implements Zend_Acl_Resource_Interface
  10. {
  11. public function getResourceId()
  12. {
  13. return sprintf('document:%s', $this->getId());
  14. }
  15.  
  16. public function canEdit($user)
  17. {
  18. return $this->can($user, 'edit');
  19. }
  20.  
  21. public function can($user, $privilege)
  22. {
  23. return $this->acl->isAllowed($user, $this, $privilege);
  24. }
  25. }
  26.  
  27. class CompanyAssertion implements Zend_Acl_Assert_Interface
  28. {
  29. public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $role = null, Zend_Acl_Resource_Interface $resource = null, $privilege = null)
  30. {
  31. return $role->getCompanyId() == $resource->getCompanyId();
  32. }
  33. }
Deallas
Tu jest bardzo dobrze wytłumaczone o czym mówił @destroyerr: http://alex-tech-adventures.com/developmen...assertions.html
mrok
Cytat
Ogólnie: kontroler powinien zapytać model czy dany użytkownik może wykonać jakąś operację.

Czyli trochę przez analogię powinienem zapytać miotłę zanim ją użyję czy mogę ja użyć? To nie model miotły ale jakiejś zmutowanej super miotły.

Ja myślałem zrobić to trochę inaczej

  1.  
  2.  
  3. class DocumentOwnerAsseration implements toCoTrzeba {
  4.  
  5. private $_request;
  6.  
  7. public function __construct(Zend_Request_Abstract $request) {
  8. $this->_request = $request;
  9. }
  10.  
  11. public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $role = null, Zend_Acl_Resource_Interface $resource = null, $privilege = null) {
  12. $document = Doctrine::getTable('Documents')->find($this->_request->getParam('doc_id'));
  13. if ($document->Company->isWorker(XX_Auth::getInstance()->getUser()))
  14. return true;
  15.  
  16. // tu jakis ladne info do flash messengera dlaczego cos jest zle
  17. return false;
  18. }
  19.  
  20. }
  21.  
  22. class AclPlugin extends Zend_Plugin_Abstract {
  23.  
  24. public function routeStartup() {
  25.  
  26. //tutaj cala zabawa z inicjacja acla
  27. $alc->allow(rola, resource, action, new DocumentOwnerAsseration($this->getRequest()));
  28.  
  29. if ($alc->isAllow())
  30. return true;
  31.  
  32. throw new Exception();
  33. }
  34.  
  35. }
  36.  


Wszystko (nie jest to jakaś strasznie skomplikowana logika) odbywa się w pluginie, żaden controller nie musi być odpalony.
Kwestia roli (księgowa, sprzątaczka, etc) jest zabezpieczona przez regułki ACLa, dodatkowy assert tylko sprawdza czy dokument należy do firmy usera.


//Dellas
Dzięki za linka - trochę podobne do tego co napisałem powyżej.
Tak kilka uwag na szybko.
1. Definicja formularza w zend_form od 1.8 ma być nie w konstruktorze, ale w init()
2. Zend_Auth w metodzie authenticate()
posiada juz kod
  1. $this->getStorage()->write($result->getIdentity());

więc powtarzanie go w AuthenticationControllerze jest niepotrzebne.
3. Nie bardzo rozumiem jak ustawiany jest "$comment" przekazywany do CommentAssertion.php ani Id ani modelu tego obieku w kodzie nie widze ;( Tobie udało sie to rozgryźć?
Spawnm
Tak po najniższej linii oporu można by ten ACL załatwić jednym zapytaniem

query('select * form documents where firma_id = ?', $_SESSION['user_firma_id'] );

I dopiero dla delete czy update sprawdzać w jakiś innych tabelach czy user jest w grupie ADMIN ew. czy w tabeli user_acl ma INSERT_DOC , UPDATE_DOC itd.
Jednak to już bym wyjął po za klasę operacji na tabeli documents.
murwazy
dokument jest przypisany do uzutkownika/firmy, przy czytaniu sprawdzasz czy zalogowany chce czytac wlasny dokument, tak samo z kasowaniem itp sprawami.
acla bym w to nie mieszal
destroyerr
Cytat
przy czytaniu sprawdzasz czy zalogowany chce czytac wlasny dokument

Mam wrażenie, że autor wie co ma sprawdzać, a pyta o to "gdzie i jak?".
Ja jednak będę polecał Acl.
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.