Italian Progettazione Database con utenti appartenenti ad associazioni diverse

udg

Expert
Licensed User
Longtime User
Mentre contate banconote, carte di credito e lingotti d'oro.. riprendo velocemente il punto sull'omonimia.
Non solo il medesimo utente (es. mrossi) potrebbe essere iscritto a più di un'associazione, ma è anche possibile che nella stessa associazione ci siano due (o più) mrossi, quindi il problema unicità dello username va affrontata comunque.
Se lo scopo è la gestione della vita associativa, credo si possa far conto sul CF visto che l'associazione dovrà comunque emettere fattura/ricevuta per i servizi erogati (dalla semplice iscrizione/rinnovo alla partecipazione a convegni, gare...). Vale anche se persone giuridiche posso essere soci.

Personalmente preferisco una tabella dedicata alle Associazioni in modo da poter attivare/disattivare tutto il loro mmateriale con un semplice campo. In più, essendo un'associazione identificata tramite un suo ID univoco, diventa facile poter estrarre (esportare) tutti i suoi dati se fosse richiesto.
Considera però che io propendo sempre per i SaaS (software as a service) e quindi, piuttosto che cercare di vendere il programma (frutto di giorni di lavoro), preferisco vendere l'abbonamento a tempo al servizio. Finché il cliente paga, il servizio è attivo..poi basta cambiare un valore in DB e tutto si ferma!

Un ulteriore possibilità è che il clienteA attivi e gestisca n Associazioni e contemporanemanete il clienteB potrebbe avere le sue m Associazioni. Ciò introdurrebbe un livello in più, ma in fondo stari gestento i "tuoi" clienti e non le "loro" associazioni.

Occhio anche alle implicazioni della GDPR.
 

Star-Dust

Expert
Licensed User
Longtime User
In ogni caso io direi che invece di inserire il nome di inserire il codice utente

quindi la tabella utenti sarebbe cosi

ID - User - Password - Nome - Via - Recapiti - Associazioni (Campo Stringa Json - cosi supporta piu voci)

Associazioni
ID - Nome - Descrizione - Indirizzo - responsabile - Recapito - Affiliati - PizzoPagato (campo boolean - True o Dead)


comunque non intervengo più, tanto a me non interessa.
 

giannimaione

Well-Known Member
Licensed User
Longtime User
Non solo il medesimo utente (es. mrossi) potrebbe essere iscritto a più di un'associazione, ma è anche possibile che nella stessa associazione ci siano due (o più) mrossi, quindi il problema unicità dello username va affrontata comunque.
ahi, ahi, mi caschi sul pisello!
chi registra i nuovi utenti?
quante volte è capito di registrare un ns. account (specialmente sui siti zozzoni), e ci viene segnalato "utente già presente ... scegli un altro nome"
 

Star-Dust

Expert
Licensed User
Longtime User
ahi, ahi, mi caschi sul pisello!
chi registra i nuovi utenti?
quante volte è capito di registrare un ns. account (specialmente sui siti zozzoni), e ci viene segnalato "utente già presente ... scegli un altro nome"
Infatti i nomi doppioni sono possibili se usi un UserID. Per accedere usi UderID (ognuno il suo) e Password, non usi Nome e Password

ID :1
User : Araz01
Password: A12234$
Nome: Arazzio Roma
 

Elric

Well-Known Member
Licensed User
Per prima cosa grazie a tutti! Anche degli OT e mezzi OT, che ho apprezzato (altrimenti come si fa ad essere la sezione che concorre per numero di post a quella internazionale?). Un bel po' di informazioni da assimilare!

Per seconda, scusate se vi scrivo ora, ma oggi è stata giornata impegnativa!

Mi pare di capire che ci sono diverse filosofie (da amorosik a Xfood, passando dal taccuino di Star-Dust e la barca di giannimaione).

Al momento io l'avevo pensata così:
  • Interfaccia in B4J per accedere e gestire i dati presenti su un database che detengo io centralmente (forse si avvicina al concetto di SaaS a cui fa cenno udg, concetto che mi piace!)

  • Tabella anagrafica utenti manager (ossia base dati di coloro che hanno accesso e possono modificare i dati dell'associazione che gestiscono) - tabella che popolo io e stabilisco se sono attivi o meno (io o la mia pletora di segretarie)
ID (Indice)int(20) AUTO_INCREMENT
nome_utente (Primaria)varchar(50)
associazione_IDtext
emailtext
attivotinyint(1)
hashblob
saltblob
in questa tabella nome e cognome mi interessa il giusto perché sono utenti manager operativi nella gestione dell'associazione ma forse non sarebbe male inserirli ugualmente... e poi: il salt lo immagazzino qui?

  • Tabella anagrafica Associazioni - tabella che popolo io (io o la mia pletora di segretarie) e stabilisco se sono attive o meno
ID (Indice)int(20) AUTO_INCREMENT
nome_associazione (Primaria)varchar(50)
via text
numero_civico text
città text
stato text
us_state text
piva text
email text
attiva tinyint(1)
per vanagloria personale ho inserito anche l'us_state giusto per complicarmi la vita. Avrò probabilmente fatto casino anche con la chiave primaria e l'indice... se ho due "mrossi" nella stessa tabella mi sa che non posso definire la colonna nome_utente come primaria, giusto?

  • Tabelle gestionali varie dell'associazione (gestione soci - e qui ci metto il Codice Fiscale -, pagamenti quote, prenotazioni etc.) che popolano gli utenti manager di cui alla prima tabella

Se un utente è gestore di due o più associazioni, pensavo che, anche con il fine di segregazione dei dati richiesta anche dal GDPR (sul punto dovrei essere abbastanza ferrato ma un'attenzione in più non guasta mai), apro due account diversi, di modo che se smette di essere gestore in un'associazione, disattivo semplicemente l'account e lo cancello dopo x mesi di inattività (sempre in ottemperanza al GDPR - anche se non saprei come automatizzare il processo di cancellazione...) mentre gli altri account vivono per i fatti propri. A proposito di GDPR, stavo pensando di pseudonimizzare tutti i dati, crittandoli e memorizzarli su DB come blob - mi ponevo il problema se è meglio farlo fare dal server piuttosto che dal programma di interfaccia ma in questo caso i dati viaggerebbero tra il client e il server in chiaro (almeno finché Star-Dust non finisce la sua libreria per SSL/TSL)... ma un drago alla volta.

Questo per non dire che popolare la colonna Associazioni della tabella utenti con Campo Stringa Json - cosi supporta piu voci - come suggerito da Star-Dust non saprei davvero come fare! Per non parlare del fatto che mi pare che da qualche parte avevo letto che è meglio che un campo abbia un solo valore (es. "mario" e "rossi" e non "mario rossi") ma leggo tante di quelle robe che chissà cosa ricordo (soprattutto a quest'ora).

Giusto per capire: questa relazione la creo con una query... ma direttamente su RDBM o tramite codice? Cioè, creo una tabella con questa struttura, ma il popolamento lo fa il RDBM o il mio codice?

ribadisco:
un ricco sfondato si gode la vita! te lo dico per esperienza personale

ecco un mio selfie sul lungomare di Napoli
View attachment 114636
Il mazzetto di contanti è superato. Oggigiorno usano i mazzetti di carte di credito.

Ma se vuoi cambiare barca dimmelo, che parlo con il commerciale e vedo di beccarmi la provvigione!

Grazie! (soprattutto se giannimaione mi fa prendere la provvigione!)
 

LucaMs

Expert
Licensed User
Longtime User
il salt lo immagazzino qui?
Non so cosa tu debba fare con hash e salt. Se vuoi crittografare ogni singolo dato, fallo nel sw, in lettura e scrittura (se SQLite c'e anche la versione cifrata, che non ho mai usato, ma ho letto di sfuggita alcuni problemi, di versione, mi pare).

Avrò probabilmente fatto casino anche con la chiave primaria e l'indice... se ho due "mrossi" nella stessa tabella mi sa che non posso definire la colonna nome_utente come primaria, giusto?
Infatti nome_utente puoi definirlo come campo chiave, per velocizzare le query; l'ID dovrebbe essere la chiave primaria (ID che non è detto sia un valore autoincrementato per forza, potresti assegnarne uno tu, magari alfanumerico).


Se un utente è gestore di due o più associazioni,
apro due account diversi,
Questo per non dire che popolare la colonna Associazioni della tabella utenti con Campo Stringa Json - cosi supporta piu voci - come suggerito da Star-Dust non saprei davvero come fare!
La stringa JSON - si potrebbe fare anche molto semplicemente una normale stringa in cui i dati siano separati da un "pipe" "|" e all'occorrenza "splittarli" (@udg, non guardare, devo adeguarmi, purtroppo 😄) ma poi voglio vederti eseguire delle query su questo campo; come dicevi:
Per non parlare del fatto che mi pare che da qualche parte avevo letto che è meglio che un campo abbia un solo valore (es. "mario" e "rossi" e non "mario rossi")
Esatto; la chiamano "atomicità" dei dati
Proprio per evitare una cosa di quel genere, un "campo lista" delle associazioni gestite da un manager, dovresti creare la tabella relazionale, che contenga esclusivamente le chiavi esterne delle tabelle "Manager" e "Associazione" (io preferisco i nomi al singolare). In questo modo avresti, ad esempio:
1623204730691.png

Nella RelManAssoc avrai, ad esempio:
un record con 1,1, indicante che Pippo (ID 1) gestisce l'associazione Filibustieri (ID 1)
un record con 2,2, indicante che Franco (ID 2) gestisce l'associazione Ladri (ID 2)
un record con 2,3, indicante che Franco (ID 2) gestisce l'associazione Delinquenti (ID 3)

Ovvero Franco gestisce due associazioni. In ogni momento puoi "sottrarre" a Franco una delle due associazioni (eliminando il terzo record sopra, ad esempio) o eliminare del tutto Franco.

Nota che nell'esempio non ho messo "Nome_Manager" e "Nome_Associazione", come nomi dei campi; motivo? Beh, se la tabella è "Manager" e ci metto un campo "Nome", non è scontato che sia il nome del manager? Stessa cosa per l'Associazione. Altrimenti dovresti fare lo stesso per tutti i campi:
Città_Manager - Città_Associazione
ID_Manager - ID_Associazione
che senso ha, che necessità c'è? Nelle query avrai Manager.Nome e Associazione.Nome (e, come vedi, il nome tabella al singolare ci sta molto meglio).


Bene, sono le 4 passate; quante cavolate avrò scritto? 😄
 
Last edited:

udg

Expert
Licensed User
Longtime User
ahi, ahi, ...
Ciao Gianni, quello è esattamente ciò che intendevo. Se vuoi lasciare piena libertà all'utente di scegliersi un suo username allora devi fare come tutti i siti che prevedono una registrazione e verificare/impedire che non si creino doppioni. Se invece, come in seguito specificato da @Elric , gli utenti manager li inserisce lui manualmente da una sua interfaccia scritta in B4J, il problema decade perché sarà lui ad evitare doppioni.

Io sottolineavo solo il fatto che il "doppione" , in quella che sembrava essere la configurazione proposta, poteva verificarsi anche solo relativamente ad una stessa associazione (es. Mario Rossi e Michele Rossi, entrambi selezionando mrossi come username). Comunque, il punto ora è superato visto che è stato chiarito che l'utente non è il socio ma un responsabile che gestisce l'intera associazione (o più di una).

@Elric : presumo che chi paghi il servizio sia l'utente manager (es. un certo importo per ogni associazione attiva); non dovresti avere il CF anche per questo tipo di figura visto che dovrai emettere fattura?

Se capisco bene hai una relazione uno-a-molti tra utente_manager (il tuo cliente) e le associazioni. Stessa situazione tra Associazione e Soci.
La soluzione indicata da @LucaMs che fa uso della tabella relazionale ti risolve entrambe le situazioni ed è molto flessibile.
Quindi, di base hai 3 tabelle dedicate (Manager, Associazioni, Soci) e 2 tabelle di relazione (Manager-Associazione e Associazione-Soci).
Una persona che sia associata a 4 Associazioni avrà 4 record nella seconda tabella di relazioni (se anche lì metti un campo di status, tipo attivo/disattivo/sospeso.. con un solo valore gestisci la situazione del socio per ciascuna associazione cui è iscritto, indipendentemente dalle eventuali altre).
Esattamente come per Manager e Associazioni.

ps: quando disegnerai le tabelle per la gestione operativa delle associazioni, ricorda di dare massima flessibilità all'impostazione perché in quel campo ognuno gestisce le cose a modo suo. Es. Quota annuale. Alcuni prevedono una quota fissa uguale per tutti, altri quote differenziate in base al tipo di socio. Alcuni fanno pagare solo le mensilità restanti alla fine dell'anno solare, altri vogliono la quota intera ed altri ancora fanno pagare i mesi restanti più l'intero anno successivo (soprattutto se la scadenza annuale è imminente). Poi ci sono tutte le clausole di sospensione dei servizi, non solo per mancati pagamenti (es. motivi disciplinari).
Il consiglio è quello di "intervistare" qualche associazione (se non hai già esperienza diretta) per carpire la varietà di situazioni e poter disegnare dall'inizio qualcosa che si adatti bene alla grande maggioranza di casi.
 

Star-Dust

Expert
Licensed User
Longtime User
L'UserID potrebbe essere il codice fiscale ed è di per sé unico e non richiede una registrazione al servizio.

Un alternativa è usare lo SPID per identificare la persona oppure la carta di identità elettronica.

Infine io farei la scansione della retina e dell'alluce così da rendere unico l'accesso.

Spero di essere stato utile. Comunque non intervengo più
 

udg

Expert
Licensed User
Longtime User
e dell'alluce
metti che sia un'associazione sportiva e l'utente abbia un caso di micosi in corso.. :)
 

Star-Dust

Expert
Licensed User
Longtime User
Come dico sempre ai miei 500 figli (ora stellantis) siete l'alluce dei miei occhi
 

Elric

Well-Known Member
Licensed User
Intanto, nuovamente grazie perché non avevo minimamente pensato ai casi di omonimia e, peggio, ai casi in cui la stessa persona lavora per associazioni diverse.

Non so cosa tu debba fare con hash e salt.
Ci creo la password (ho seguito il metodo usato anche in questo esempio nella parte "Login"). Qui leggo "è abitudine tenere segreto il valore salt e conservarlo separatamente dal database delle password"; che vuol dire che lo devo conservare in un'altra tabella separata da quella in cui conservo i dati degli utenti manager?

Se la risposta a questa domanda è "si", la relazione 1:1 tra utente e salt la realizzo mediante un ulteriore tabella relazionale:
1623223648113.png


o semplicemente nella tabella in cui conservo il salt, che sarebbe quindi progettata così:
1623223729008.png
?

La stringa JSON - si potrebbe fare anche molto semplicemente una normale stringa in cui i dati siano separati da un "pipe" "|" e all'occorrenza "splittarli" (@udg, non guardare, devo adeguarmi, purtroppo 😄) ma poi voglio vederti eseguire delle query su questo campo;
Con calma organizziamo uno spettacolo in cui mi esibisco in questa attività e lo pubblicizzeremo come "Elric's json queries is the new Zelig"... e facciamo i soldi!

Nella RelManAssoc avrai, ad esempio:
un record con 1,1, indicante che Pippo (ID 1) gestisce l'associazione Filibustieri (ID 1)
un record con 2,2, indicante che Franco (ID 2) gestisce l'associazione Ladri (ID 2)
un record con 2,3, indicante che Franco (ID 2) gestisce l'associazione Delinquenti (ID 3)
Tutto chiaro e decisamente più snello, ma in un'ottica GDPR compliant (o adempimento alla normativa prevista dal RGPD), partendo dal presupposto che il manager è un associato e che il titolare dei dati è l'associazione, è meglio se gli account dei manager sono separati in maniera stagna: virtualmente ti metti il cappello dell'associazione che devi seguire in quel momento e con un accesso vedi solo ed esclusivamente i dati di quell'associazione. È un discorso un po' lungo e merita approfondimenti a parte (un assessment della situazione, verifica della titolarità del dato etc.) e andrei OT in maniera molto noiosa.

Nota che nell'esempio non ho messo "Nome_Manager" e "Nome_Associazione", come nomi dei campi; motivo? Beh, se la tabella è "Manager" e ci metto un campo "Nome", non è scontato che sia il nome del manager? Stessa cosa per l'Associazione. Altrimenti dovresti fare lo stesso per tutti i campi:
Città_Manager - Città_Associazione
ID_Manager - ID_Associazione
che senso ha, che necessità c'è? Nelle query avrai Manager.Nome e Associazione.Nome (e, come vedi, il nome tabella al singolare ci sta molto meglio).
👍
Bene, sono le 4 passate; quante cavolate avrò scritto? 😄
👽

@Elric : presumo che chi paghi il servizio sia l'utente manager (es. un certo importo per ogni associazione attiva); non dovresti avere il CF anche per questo tipo di figura visto che dovrai emettere fattura?
No, è l'associazione, che indicherà chi dei suoi associati avrà accesso ai dati. La fattura è intestata all'associazione.

Se capisco bene hai una relazione uno-a-molti tra utente_manager (il tuo cliente) e le associazioni. Stessa situazione tra Associazione e Soci.
La soluzione indicata da @LucaMs che fa uso della tabella relazionale ti risolve entrambe le situazioni ed è molto flessibile.
Quindi, di base hai 3 tabelle dedicate (Manager, Associazioni, Soci) e 2 tabelle di relazione (Manager-Associazione e Associazione-Soci).
Una persona che sia associata a 4 Associazioni avrà 4 record nella seconda tabella di relazioni (se anche lì metti un campo di status, tipo attivo/disattivo/sospeso.. con un solo valore gestisci la situazione del socio per ciascuna associazione cui è iscritto, indipendentemente dalle eventuali altre).
Esattamente come per Manager e Associazioni.
Ipotizziamo che
  • MRossi ha la carica di tesoriere dell'associazione Filibustieri e la carica di segretario nell'associazione Corsari; e
  • RVerdi è il presidente dell'associazione Filibustieri.
È necessario che quando MRossi lavora insieme a RVerdi sui dati dell'associazione Filibustieri, RVerdi non possa in alcun modo vedere i dati dei soci dell'Associazione Corsari. Inoltre bisogna mitigare l'errore umano: mentre MRossi tratta i dati dei soci dell'Associazione Filibustieri non deve modificare inavvertitamente anche quelli dell'associazione Corsari.

Questo perché le singole associazioni sono titolari dei rispettivi dati e i loro dirigenti semplici esecutori. Qualora ci fosse GBianchi che fa da commercialista (e quindi è un responsabile del trattamento) la situazione non cambia, se la titolarità dei dati a cui accede è in capo alle associazioni; quindi GBianchi avrà un suo account legato alle.

ps: quando disegnerai le tabelle per la gestione operativa delle associazioni, ricorda di dare massima flessibilità all'impostazione perché in quel campo ognuno gestisce le cose a modo suo. Es. Quota annuale. Alcuni prevedono una quota fissa uguale per tutti, altri quote differenziate in base al tipo di socio. Alcuni fanno pagare solo le mensilità restanti alla fine dell'anno solare, altri vogliono la quota intera ed altri ancora fanno pagare i mesi restanti più l'intero anno successivo (soprattutto se la scadenza annuale è imminente). Poi ci sono tutte le clausole di sospensione dei servizi, non solo per mancati pagamenti (es. motivi disciplinari).
Il consiglio è quello di "intervistare" qualche associazione (se non hai già esperienza diretta) per carpire la varietà di situazioni e poter disegnare dall'inizio qualcosa che si adatti bene alla grande maggioranza di casi.
4 anni di tesoriere e altri 4 di affiancamento in un'associazione, più 3 di segretario e 2 di affiancamento in un'altra, direi che un'idea me la sono fatta! :) Ma fai bene a ricordarmelo perché di alcune casistiche non ho avuto esperienza!

Comunque, in informatica si usano meno gli alluci e più... gli indici 😂
Sto cercando "Alluci" nel phpmyadmin ma trovo solo "Indici"...
 

Attachments

  • 1623223694099.png
    1623223694099.png
    1.5 KB · Views: 100

LucaMs

Expert
Licensed User
Longtime User
Ci creo la password (ho seguito il metodo usato anche in questo esempio nella parte "Login"). Qui leggo "è abitudine tenere segreto il valore salt e conservarlo separatamente dal database delle password"; che vuol dire che lo devo conservare in un'altra tabella separata da quella in cui conservo i dati degli utenti manager?
Crea una pw di una dozzina di caratteri, numeri, letterali (sia maiuscole che minuscole) e segni speciali. La probabilità che qualcuno la indovini (usando sw) sarà (a occhio) di una su 1.000 miliardi (si potrebbe calcolare; [numero di caratteri disponibili - già soltanto gli alfabetici sono 52] ^ [lunghezza pw]).

Sto cercando "Alluci" nel phpmyadmin ma trovo solo "Indici"...
Credo siano solo in MS SQLServer 😄
 

LucaMs

Expert
Licensed User
Longtime User
Crea una pw di una dozzina di caratteri, numeri, letterali (sia maiuscole che minuscole) e segni speciali. La probabilità che qualcuno la indovini (usando sw) sarà (a occhio) di una su 1.000 miliardi (si potrebbe calcolare; [numero di caratteri disponibili - già soltanto gli alfabetici sono 52] ^ [lunghezza pw]).
70^12=13.841.287.200.999.999.537.152

Avendo messo 70 come caratteri disponibili (26 lettere minuscole, 26 maiuscole, 10 cifre, 8 caratteri speciali) e lunghezza pw 12.
Io non riesco a leggere quel numero 😄
13.841 miliardi di miliardi.
 
Top