2013-02-13 9 views
13

Symfony ACL mi permette di concedere l'accesso a un soggetto, e quindi controllare che:Come filtrare le mie domande Doctrine con Symfony ACL

if (false === $securityContext->isGranted('EDIT', $comment)) { 
    throw new AccessDeniedException(); 
} 

Tuttavia, se ho migliaia di entità nel database e l'utente ha accesso solo a 10 di essi, non voglio caricare tutte le entità in memoria e idratarle.

Come si può fare un semplice "SELECT * FROM X" mentre si filtra solo sulle entità a cui l'utente ha accesso (a livello SQL)?

+1

Hai guardato questa risposta SO? http://stackoverflow.com/questions/9652755/best-way-to-manage-user-group-object-permissions-with-symfony2 –

+0

Hai provato a utilizzare [createQuery] (http: //docs.doctrine-project metodo .org/it/latest/reference/dql-doctrine-query-language.html # dql-select-clause)? –

risposta

3

Beh, c'è: non è possibile.

Nell'ultimo anno ho lavorato su un sistema ACL alternativo che consentiva di filtrare direttamente nelle query del database.

La mia azienda ha recentemente deciso di open source, quindi qui è: http://myclabs.github.io/ACL/

+1

C'è una soluzione alternativa però. È possibile elencare l'ACE per SecurityIdentity e UserSecurityIdentity e quindi inserire la clausola WHERE nella query senza partecipare, solo gli id. – gregor

+0

Sì, ma è una query del tipo 'WHERE id IN (1, 2, 3, ...)', che (se data molti id) sarebbe molto inefficiente :(Ma hai ragione che vale la pena menzionare.Inoltre, sarebbe 2 Query DB invece di una (con un JOIN). –

+0

non vero, WHERE IN() dovrebbe essere veloce - http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_in. il limite al numero di ID dipende dalla dimensione del pacchetto di query consentito, che per impostazione predefinita è 16 MB (aumentabile a 1 GB), sufficiente per almeno 1 milione di IDS nella query (credo). Il numero di query dipende da dove si memorizza le regole ACL - potrebbe essere in un file o memcached - quindi 1 query tutte insieme – gregor

-1

Si potrebbe dare un'occhiata allo Doctrine filters. In questo modo puoi estendere tutte le domande. Non l'ho ancora fatto e ci sono alcune limitazioni documentate. Ma forse ti aiuta. Troverai una descrizione delle tabelle del database ACL here.

UPDATE

Ogni filtro restituirà una stringa e tutte quelle stringhe vengono aggiunti alle query SQL in questo modo:

SELECT ... FROM ... WHERE ... AND (<result of filter 1> AND <result of filter 2> ...) 

Anche l'alias di tabella viene passato al metodo del filtro. Quindi penso che tu possa aggiungere qui sottoquery per filtrare le tue entità.

+2

Grazie per la tua risposta, non l'ho visto. I filtri Doctrine non aiutano perché non consentono di JOIN con una tabella, consentono solo di aggiungere SQL nella clausola WHERE. –

0

Come sottolineato dal @gregor nella discussione precedente,

Nella tua prima domanda, ottenere una lista (con un costume query) di tutti gli object_identity_ids (per una specifica entità/classe X) a cui un utente ha accesso.

Quindi, quando si esegue una query su un elenco di oggetti per entità/classe X, aggiungere "IN (object_identity_ids)" alla query.

Matthieu, non ero soddisfatto rispondendo con più congetture (poiché le mie congetture non aggiungono nulla di prezioso alla conversazione). Quindi Ho eseguito alcuni benchmark su questo approccio (Digital Ocean 5 $/mo VPS).

Benchmark

Come previsto, dimensione della tabella non importa quando si utilizza l'approccio matrice IN. Ma una grande dimensione dell'array fa sì che le cose vadano fuori controllo.

Quindi, Join approach vs IN array approach?

JOIN è davvero migliore quando la dimensione dell'array è enorme. MA, questo presume che non dovremmo considerare la dimensione della tabella. Risulta, in pratica, IN array è più veloce - tranne quando c'è una grande tabella di oggetti e le voci acl coprono quasi tutti gli oggetti (vedi la domanda collegata).

Ho ampliato il mio ragionamento su una domanda separata.Si prega di vedere When using Symfony's ACL, is it better to use a JOIN query or an IN array query?