La comunità italiana su CakePHP

You are not logged in. Please login or register.


Pages: 1

Atom RSS

Posts [ 18 ]

ToX

Topic: ACL ma anche no. Che ne dite di...

stavo provando a cimentarmi con le ACL ma non mi piacciono... troppo macchinoso, troppe query... troppo bleah da far andare big_smile

stavo pensando ad ampliare una soluzione che ho già adottato, qualcosa di simile a questo:

groups -> id, username, password etc
groups_users -> collegamento fra utenti e gruppi... che hanno relazione habtm
users -> id, username, password etc
permissions -> id, group_id, controller, action, granted (booleano), in sostanza qua ci stanno i controller e le action, tramite una lista che viene generata da una funzione apposita (possibile? credo di si...), granted è un booleano, indica se il gruppo ha i permessi oppure no di usare quella funzione. esiste una action fittizia "*" che indica che il gruppo può fare qualunque cosa su quel controller

e questo è, pressappoco, il database
poi ci sarebbe un semplice backend per gestire il tutto

infine, e qua è dove avviene il controllo, pensavo ad una requestAction o qualcosa di simile che faccia il controllo dei permessi, qualcosa tipo

function vattelapesca() {
    $this->requestAction('controller' => 'permissions', 'action' => 'check', named => array('con' => 'miocontroller', 'act' => 'miaaction');
}

/* controller permissions, o meglio un component forse */
function check ($con, $act) {
    controllo se l'utente è loggato e a quale gruppo appartiene, se non è loggato appartiene al gruppo "guests"
    recupero il group_id
    controllo nella tabella delle permissions se ha i permessi "granted" per il controller e l'azione, in caso affermativo return true, altrimenti lo sbatto alla pagina di login, o a quella di partenza avvisandolo che non ha i permessi per compiere quell'azione...
}

il vantaggio di questo sistema è che, utilizzando la stessa funzione, si potrebbe creare anche un'estensione linkIfPermitted dell'helper html...


che dite, potrebbe funzionare? potrebbe essere funzionale? comincio a scrivere?big_smile

Last edited by ToX (11-03-2009 18:24:34)

ToX

Re: ACL ma anche no. Che ne dite di...

ripensandoci... forse invece di fare quel controllo requestAction in ogni action conviene farla in un beforeFilter, così verrebbe lanciata automaticamente senza aggiungere altro alle funzioni...

ToX

Re: ACL ma anche no. Che ne dite di...

come elencare tutti i controller/azioni... smile

http://cakebaker.42dh.com/2006/07/21/ho … ntrollers/

pineye

Re: ACL ma anche no. Che ne dite di...

La vera potenza di ACL è l'ereditarietà dei permessi. E' vero che il meccanismo è macchinoso e produce mille query, ma è davvero potente. Solo che non sempre è necessario.

Il sistema che proponi secondo me si pone a metà tra le complesse ACL e un semplice sistema di controllo. Per essere davvero utile dovresti cercare di renderlo il più semplice e trasparente possibile, tutto automatico, il che non è proprio facile a mio avviso.

Interessante

ToX

Re: ACL ma anche no. Che ne dite di...

si, sostanzialmente sarebbe una via di mezzo in effetti...

non so, pensavo di tentare per un sito che sto sviluppando... togliendo le acl, che funzionano ma non mi soddisfano pienamente, in favore di questo, che sarebbe forse più semplice da gestire (ed avrebbe il linkifpermitted big_smile)

Luizz

Re: ACL ma anche no. Che ne dite di...

Tox, io ho scritto un sistema simile al tuo, dove si possono associare utenti ai gruppi e  assegnare permessi ai gruppi.
I permessi sono del tipo controller/azione
Poi ho aggiunto nel permesso il nome di una tabella e i campi con i valori per cui il gruppo può accedere o meno.
Quando in un controller esegui una qualsiasi query (find o altro metodo) nel app_model viene aggiunta la condizione per limitare l'accesso solo alle tabelle/record consentiti.
Con l'uso delle wildcard "*" posso far accedere a tutti i metodi di un controller o a tutti i record di una tabella.

E' tutto piuttosto complesso (bisogna andare a mettere codice in app_model, app_controller, ecc) e devo ancora (da mesi e mesi) sviluppare l'interfaccia per un'assegnazione + agevole dei permessi.

Conclusione: rimango dell'idea di utilizzare le ACL per implementare un sistema definitivo di permessi soprattutto perchè è supportato dal gruppo di sviluppo di Cake e questo lo rende per me più robusto e mantenibile, oltre a essere più flessibile come dice pineye

ToX

Re: ACL ma anche no. Che ne dite di...

sono riuscito a trovare una soluzione, con una bruttissima query hardcoded riesco ad ottenere una lista di tutte le azioni disponibili ad una ARO:

        function permissions($aroId) {

        $sql = "SELECT DISTINCT alias
            FROM
            (
            SELECT
            user_id.aro_id
            ,(
            SELECT
            case when controler is null then method WHEN master is null then concat(controler,'/',method) else concat(master,'/',controler,'/',method) end as alias
            FROM
            (SELECT id,`alias` as method, (SELECT `alias` FROM acos WHERE id=t.parent_id) as controler, (SELECT `alias` FROM acos WHERE id=(SELECT `parent_id` FROM acos WHERE id=t.parent_id)) as `master` FROM acos t) Aco
            WHERE Aco.id=u.aco_id OR Aco.id=p.aco_id
            ) as name,
            CASE WHEN u.aco_id=0  OR u.aco_id is NULL  THEN p.aco_id  ELSE u.aco_id  END as aco_id,
            CASE WHEN u._create=0 OR u._create is NULL THEN p._create ELSE u._create END as _create,
            CASE WHEN u._read=0   OR u._read is NULL   THEN p._read   ELSE u._read   END as _read,
            CASE WHEN u._update=0 OR u._update is NULL THEN p._update ELSE u._update END as _update,
            CASE WHEN u._delete=0 OR u._delete is NULL THEN p._delete ELSE u._delete END as _delete
            FROM
            (SELECT 'a' as flag,$aroId as aro_id) user_id
            LEFT JOIN
            (
            SELECT 'a' as mark1,aco_id,`_create`,`_read`, `_update`, `_delete` FROM `aros_acos` AS `Permission` LEFT JOIN `aros` AS `Aro` ON (`Permission`.`aro_id` = `Aro`.`id`) LEFT JOIN `acos` AS `Aco` ON (`Permission`.`aco_id` = `Aco`.`id`) WHERE `Permission`.`aro_id` = $aroId  ORDER BY `Aco`.`lft` ) u ON u.mark1=user_id.flag
            LEFT JOIN
            (
            SELECT 'a' as mark2,aco_id,`_create`,`_read`, `_update`, `_delete`  FROM `aros_acos` AS `Permission` LEFT JOIN `aros` AS `Aro` ON (`Permission`.`aro_id` = `Aro`.`id`) LEFT JOIN `acos` AS `Aco` ON (`Permission`.`aco_id` = `Aco`.`id`) WHERE `Permission`.`aro_id` = (
            SELECT id
            FROM aros
            WHERE id=(SELECT parent_id from aros WHERE id=$aroId)
            )
            )p ON p.mark2=user_id.flag
            WHERE u._create=1 OR u._read=1 or u._update=1 or u._delete=1
            OR p._create=1 OR p._read=1 or p._update=1 or p._delete=1
            ) tt
              LEFT JOIN
            (
            SELECT `Aco`.`id` , `Aco`.`parent_id` , `Aco`.`model` , `Aco`.`foreign_key` , `Aco`.rght,`Aco`.lft,
            case when controler is null then method WHEN master is null then concat(controler,'/',method) else concat(master,'/',controler,'/',method) end as alias
            FROM
            (SELECT *, `alias` as method, (SELECT `alias` FROM acos WHERE id=t.parent_id) as controler, (SELECT `alias` FROM acos WHERE id=(SELECT `parent_id` FROM acos WHERE id=t.parent_id)) as `master` FROM acos t) Aco
            ) tmp_aco
            ON tmp_aco.id=tt.aco_id OR tmp_aco.alias like concat(tt.name,'%')
        ";

        $permissions = $this->User->query($sql);
        $permissions = Set::extract('/tmp_aco/alias', $permissions);
        return $permissions;
        }

ora sarebbe semplice far funzionare il tutto... ma di una bruttezza inumana.

ho così deciso che il sistema di accessi, anche questa volta, lo scriverò a manina big_smile

ToX

Re: ACL ma anche no. Che ne dite di...

sto guardando un po' in giro, e vedo che ci sono dei discreti plugin per l'autenticazione in giro...


questo ad esempio non sembra male:
http://www.studiocanaria.com/articles/c … _revisited

Luizz

Re: ACL ma anche no. Che ne dite di...

Qualche tempo fa, quando volevo usare per forza le ACL, avevo trovato un sistema che permetteva di gestire i permessi con la logica degli utenti e gruppi, ma impiegando ARO e ACO....
Se lo ritrovo lo posto.

ToX

Re: ACL ma anche no. Che ne dite di...

se è un coso fatto in ajax l'ho visto anche io... però sembra che non funzioni così bene, e mi rimane aperto il problema del "linkIfPermitted" che... non esiste big_smile

cioè mi sembra una cosa così banale da non riuscire a crederci... cake ormai ordina anche il caffè al bar più vicino con un semplice comando $this->requestCoffee, possibile che non ci sia un sistema per controllare se un utente ha i permessi per lavorare su un certo controller prima di proporne il link?

ToX

Re: ACL ma anche no. Che ne dite di...

gente ho implementato il plugin per l'autenticazione che ho linkato, e l'ho modificato...

ora c'è anche il famigerato $link->linkIfPermitted, che funziona esattamente come $html->link (è sostanzialmente un wrapper che va a passare ciò che gli viene dato dopo aver fatto i suoi controlli)

il tutto senza fare alcuna query aggiuntiva, fa una sola query la prima volta che accedi e poi rimane tutto salvato in una variabile di sessione smile

appena rifinisco il tutto, posto smile

ToX

Re: ACL ma anche no. Che ne dite di...

... cioè più che rifinire, mi servirebbe una funzione che mi fa l'elenco di tutti i controller e le azioni disponibili

confronti l'elenco con la tabella permissions, e quello che manca lo aggiunge big_smile

ToX

Re: ACL ma anche no. Che ne dite di...

e già

bello il linkIfPermitted

ma è solo un link, il contenitore (<li> o chi per lui) come lo controllo? mad

uff, toccherà studiare qualcosa neutral

ToX

Re: ACL ma anche no. Che ne dite di...

lampo di genio, trovata la soluzione smile era semplice in effetti big_smile

ora faccio qualcosa di simile a (vado a memoria)

if ($link->checkPermissions(array('posts:add', 'comments:edit') == true) {
  echo "<li>" . $eccetera;
}

ora si tratta di sistemare un po' di cose, renderlo utilizzabile come si deve, e poi posto il tutto:)

ToX

Re: ACL ma anche no. Che ne dite di...

gente, sono disperato big_smile

sto cercando di implementare un sistema in cui i permessi per l'utente siano dati attraverso un gruppo, quindi con le normali regole su database, e non hardcoded in ogni controller... o in app_controller.

qualche idea? neutral

saintpumpkin

Re: ACL ma anche no. Che ne dite di...

ehm, ma a che serve acl ? smile

Luizz

Re: ACL ma anche no. Che ne dite di...

saintpumpkin wrote:

ehm, ma a che serve acl ? smile

http://it.wikipedia.org/wiki/Lista_di_c … li_accessi
http://book.cakephp.org/view/641/Simple … pplication

zuck

Re: ACL ma anche no. Che ne dite di...

Io ho creato un semplice sistema ACL che sfrutta un'idea simile: utenti, gruppi e permessi associati ai singoli URLs. Il tutto è farcito con l'ereditarietà dei permessi.

Il sistema è piuttosto trasparente e il meccanismo automatizzato:

- Se l'utente non è loggato, vige l'AuthComponent (e le "allowed actions").
- Se l'utente è loggato entra in gioco il SimpleACL:
-- Se l'utente possiede il permesso di accedere al link corrente allora eseguilo.
-- Se l'utente non possiede il permesso, verifica se il suo gruppo lo possiede, in tal caso eseguilo.
-- Se il gruppo di appartenenza dell'utente non possiede il permesso, cerca nei gruppi genitori risalendo la gerarchia finchè il permesso viene trovato.
-- Se il permesso non è presente in nessuno dei nodi della gerarchia, vieta l'esecuzione.

Per finire, anche i links sfruttano una sorta di "ereditarietà intelligente", esempio:

- "Utente1" appartiene al gruppo "Users" che discende dal gruppo "Guests".
- L'azione è "documents/view/1".
- "Guests" ha negato l'accesso a "documents". Questo significa che tutte le azioni di "DocumentsController" sono negate al gruppo "Guests".
- "Users" ha consentito l'accesso a "documents/view", quindi può accedere a "documents/view/1" ma non a tutte le altre azioni di "DocumentsController".
- Quindi "Utente1" può accedere a "documents/view/1".

Ovviamente l'ultimo permesso sovrascrive i precedenti, perciò se "Utente1" avesse negato l'accesso a "documents/view" allora non avrebbe potuto accedere nemmeno a "documents/view/1" (nonostante il gruppo "Users" possieda questo permesso).

Con un behavior, un component e un helper si risolve il tutto con 2 righe di codice in croce (e ovviamente il riempimento del DB dei permessi, che tuttavia possono essere assegnati a partire dai gruppi in modo da risparmiare righe sfruttando l'ereditarietà).

Posts [ 18 ]

Guest posting is disabled. You must login or register to post a reply.

Pages: 1

Topic info

0 guests and 0 users are reading this topic now


Forum quick jump menu

Currently used extensions: pun_topic_online_users, pun_karma, pun_admin_hook_navigator, pun_bbcode. Copyright © 2008 PunBB

[ Generated in 1.134 seconds, 12 queries executed ]