Relazioni complicate!

Struttura:


utenti

 id

 user

 pass

 ...


zone

 id

 nome


zone_utenti

 id_utente (utenti.id)

 id_zona (zone.id)


azioni

 id

 id_utente (utenti.id)

 descrizione

 ...

Esempio di dati nel database:


utenti

ID | User

1  | nicola

2  | pippo

3  | pluto


zone

ID | nome

1  | Area Uno

2  | Area Due

3  | Area Tre


zone_utenti

id_utente | id_zona 

1         | 1     

1         | 2       

2         | 1

3         | 3


azioni

ID | id_utente | descrizione

1  | 2         | Pippo fa la spesa

2  | 3         | Pluto fa jogging

Ora se un utente si logga dovrebbe poter vedere solo le azioni fatte dagli utenti che sono nella stessa sua zona.

Ci sono in pratica delle relazioni MANY::MANY multiple per la stessa tabella "utenti".

Nell’esempio sopra loggandomi come “nicola” dovrei vedere solo le azioni di “pippo” ma non di “pluto” perché non è nelle mie zone!

Nel modello utenti ho le relazioni




'azioni' => array(self::HAS_MANY, 'Azioni', 'id_utente'),

'zone' => array(self::MANY_MANY, 'Zone', 'zone_utenti(id_utente, id_zona)'),



Nel modello azioni ho




'utente' => array(self::BELONGS_TO, 'Utenti', 'id_utente', 'with' => 'zone'),



Secondo voi qual’è possibile scrivere un CActiveDataProvider che tramite un CDbCriteria mi tiri fuori questa lista?

Assomiglia ad un sistema RBAC. Quindi la domanda sorge spontanea: perché reinventare la ruota quando esiste già dentro Yii il codice per gestire queste cose?

Perché ci assomiglia ma RBAC non mi piace proprio.

Inoltre questa struttura ha già dietro un sistema di controllo dei ruoli che è ad un livello diverso da questo delle aree.

Per finire, mi sembra un buon esercizio quindi vorrei comunque arrivare ad avere una soluzione fatta a mano e fatta bene :)

Quello che tu chiami area in RBAC è un gruppo (e non un ruolo). Se si tratta di un esercizio, fai bene a farlo. Ma ti ricordo che RBAC è un pattern che risolve già il tuo tipo di problema. Se il tuo è un pattern diverso, mi farebbe piacere capire in che cosa lo è ed in che modo può essere sfruttato meglio di RBAC ed in che contesto.

Dicevo che io ho già una gestione dei Ruoli nella mia App ed ora vorrei implementare le aree.

RBAC probabilmente fa già questo ma è molto pesante e non mi va di utilizzarlo su un numero ristretto e statico di ruoli e aree, vorrei quindi mantenere la mia implementazione dei ruoli che è molto leggera e scrivere ora quella delle aree senza appesantire tutto con RBAC.

Inoltre non mi piace avere le business rule nel database, in generale non mi piace avere del codice PHP nel database e dover fare un’eval() per svariati motivi di sicurezza e manutenzione.

Il mio problema quindi, essendo non solo di codice ma anche di prestazioni, non viene risolto da RBAC! :)

Nel mentre non mi sono ancora venute idee carine per farlo! ???

Tu per caso sai su RBAC qual’è il metodo che fa il check del gruppo che dici?

Magari da li posso prendere qualche spunto ma non lo trovo!

Prova a vedere checkAccess, non vorrei sbagliarmi, ma si preoccupa lui di capire se l’utente ha il permesso o il gruppo giusto.

Mmm no non ho trovato nulla che possa servirmi :(

Ammetto che sia un po’ poco chiaro a prima vista, ma credo che checkAccess sia il metodo giusto.

fonte: CWebUser::checkAccess()




public function checkAccess($operation,$params=array(),$allowCaching=true) 

{ 

    if($allowCaching && $params===array() && isset($this->_access[$operation])) 

        return $this->_access[$operation]; 


    $access=Yii::app()->getAuthManager()->checkAccess($operation,$this->getId(),$params); 

    if($allowCaching && $params===array()) 

        $this->_access[$operation]=$access; 


    return $access; 

}



O forse non ho capito cosa cerchi.

Io non devo verificare e un utente è di quella zona e basta.

Io devo tirare su una lista degli utenti presenti in una o più zone dell’utente loggato!

Allora non avevo capito nulla: RBAC non ha nulla a che fare con quello che ti serve. Se ho capito tu vuoi sapere chi sta facendo cosa e dove?

Come detto all’inizio.

Se mi loggo come utente "nicola" devo vedere solo le azioni fatte dagli altri utenti che hanno le mie zone.

Con i dati in esempio vedrei le azioni di pippo in quanto siamo entrambi nella Zona "Area Uno".

Intanto ho risolto con una cosa bruttina, nel CActiveDataProvider delle azioni filtro in questo modo:


$criteria->with = array(

'utente' => array(

    ...

    'condition' => 'utente.id IN ( 

SELECT id_utente 

FROM zone_utenti

WHERE id_zona IN ( '.implode(',', $loggedUser->getRelatedZonesId()).' ) )',

    )

); 

dove


$loggedUser->getRelatedZonesId

restituisce le zone dell’utente loggato <_<

Scusami ma quello che scrivi per me è confuso: vuoi vedere le azioni di chi ha le stesse zone di un utente oppure di chi si trova nella stessa zona. A questo punto non capisco il tuo concetto di zona. Ti chiedo di essere più chiaro perché così io non capisco proprio quale problema stai cercando di risolvere.

Guarda la struttura del DB proposta.

utenti è la tabella degli utenti che si loggano.

zone è un tabella con la descrizione delle Zone appunto.

azioni è una tabella con la descrizione di Azioni inserite dagli utenti.

zone_utenti è la tabella che mi mantiene la relazione molti a molti.

Se io mi loggo e vado in /Azioni/index (è un esempio), dovrei vedere tutte le azioni degli utenti che sono nelle mie zone!

La zona vedila tipo un ruolo, un utente può avere una o più zone e un utente può vedere solo le azioni fatte nelle sue zone (quindi dagli utenti che hanno le sue zone).

Ti ho confuso di più?

Tu usi il verbo essere ed il verbo avere in maniera interscambiabile.

"utenti che sono nelle mie zone"

"che hanno le sue zone"

Si ed e se contestualizzata è pure una prassi giustificata dall’accademia della crusca! :lol:

[b]versione 1

[/b]

Se io mi loggo e vado in /Azioni/index (è un esempio), dovrei vedere tutte le azioni degli utenti che hanno delle zone in comune con le mie!

La zona vedila tipo un ruolo, un utente può avere una o più zone e un utente può vedere solo le azioni fatte nelle sue zone (quindi dagli utenti che hanno delle zone in comune con lui).

[b]versione 2

[/b]

Se io mi loggo e vado in /Azioni/index (è un esempio), dovrei vedere tutte le azioni degli utenti che sono nelle mie zone!

La zona vedila tipo un ruolo, un utente può essere in una o più zone e un utente può vedere solo le azioni fatte nelle zone in cui è (quindi dagli utenti che sono in una sua stessa zona).

Io ho capito entrambe le versioni. Tu sei consapevole che sono due problemi completamente differenti e che uno riguarda azioni svolte in un arco temporale e l’altro riguarda azioni che si possono compiere in termini assoluti?

No non sono completamente differenti ma assolutamente identici in questo caso.

Partendo dall’esempio iniziale non è importante quando tutto questo succede altrimenti avrei dato dei parametri temporali e quindi considerando i dati di esempio riportati (quindi ad un tempo X) il problema proposto si presenta identico in entrambe le situazioni.

Ora penso sia il caso di finirla con cavilli linguistici inutili (e opinabili) quando il problema mi sembra ben chiaro! :)

Guarda, a questo punto ti chiedo di aprire un nuovo thread dove io non scriverò. Vorrei aiutarti ma in questo thread non mi riesce. Ti chiedo di aprire un nuovo thread perché molti non leggono quelli già avviati. Buona fortuna.