Questa domanda si presentava mentre si progettava un sistema ACL dedicato per un'applicazione personalizzata, ma penso che si applichi ai sistemi ACL in generale, poiché non ho scoperto come affrontare questo problema osservando alcuni dei sistemi mainstream, come Zend_ACL
.creazione di un sistema ACL dinamico "bidirezionale"
Nella mia applicazione, le autorizzazioni sono concesse in modo dinamico, ad esempio: un utente ottiene le autorizzazioni di visualizzazione su un'attività perché è un membro del team a cui è collegata l'attività. Questo presuppone che tu abbia sempre un Employee
(utente) che vuole eseguire un'azione (visualizza/modifica/ecc.) Su uno Item
(uno degli oggetti nella mia applicazione, ad esempio Attività, Squadra, ecc.). Questo è sufficiente per il mio uso mirato;
$Activity = new Activity($_POST['activity_id']);
$Acl = new Acl($Activity);
if (!$Acl->check('edit') {
throw new AclException('no permission to edit');
}
La mia classe Acl
contiene tutte le regole di business per concedere le autorizzazioni, e vengono creati 'on the fly' (anche se a volte nella cache per motivi di prestazioni);
/**
* Check the permissions on a given activity.
* @param Activity $Activity
* @param int $permission (optional) check for a specific permission
* @return mixed integer containing all the permissions, or a bool when $permission is set
*/
public function checkActivity(Activity $Activity, $permission = null) {
$permissions = 0;
if ($Activity->owner_actor_id == $this->Employee->employee_id) {
$permissions |= $this->activity['view'];
$permissions |= $this->activity['remove'];
$permissions |= $this->activity['edit'];
} elseif (in_array($this->Employee->employee_id, $Activity->contributor_ids_arr)) {
$permissions |= $this->activity['view'];
} else {
/**
* Logged in user is not the owner of the activity, he can contribute
* if he's in the team the activity is linked to
*/
if ($Activity->getTeam()->isMember($this->Employee)) {
$permissions |= $this->activity['view'];
}
}
return ($permission ? (($permission & $permissions) === $permission) : $permissions);
}
Questo sistema funziona così com'è.
Il problema con questo approccio si verifica quando si desidera "invertire" le regole ACL. Ad esempio, "recupera tutte le attività che sono autorizzato a modificare". Non voglio inserire alcuna logica come WHERE owner_actor_id = $Employee->employee_id
nel codice che richiede le attività, poiché questa è la responsabilità della classe Acl
e dovrebbe essere mantenuta centralizzata. Con l'implementazione corrente, non ho altra scelta che recuperare tutte le attività nel codice e quindi dichiararle una per una. Questo è ovviamente un approccio molto inefficiente.
Quindi quello che sto cercando è alcune idee su una buona architettura (o un puntatore a un'implementazione ACL esistente o alcuni modelli di progettazione rilevanti) per creare un sistema di ACL che in qualche modo possono fare entrambe le cose e hasPermission($Item, $permission)
fetchAllItems($permission)
, idealmente con il stesso insieme di regole aziendali.
Grazie a tutti in anticipo!
Ho guardato il Zend_ACL
realizzazione, ma che si concentra più sulle autorizzazioni generali. Ho trovato anche le seguenti domande qui su SO:
Ma purtroppo non sembrano rispondere alla domanda sia.
Qual è l'argomento contro mettendo i 'fetchAllItems()' metodo nella 'Classe acl'? Non sono sicuro di capire davvero la domanda. – erisco