September 21, 2007

Scripting VB.NET

Tastiera infrarossiQuesta cosa non mi era ancora capitata. Lavorando ad uno script molto quick e very dirty per sistemare i problemi di profili roaming di Citrix mi sono trovato davanti ad un muro che mi ha sbarrato la strada per due giorni. In pratica uno script in VB.NET che funzionava perfettamente in locale, messo in produzione su un server 2003 continuava ad andare in Exception. E gira e rigira, riscrivi il programma in un altro modo. Ho preso e copiato del codice da un’applicazione che avevo sviluppato in passato e…. non funzionava piu’ in locale! Due giorni di debug e poi mi son detto… ma si… proviamo a fare questo.

La porzione di codice incriminata e’:

Private Sub jobTicker_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles jobTicker.Tick

If Not scriptingWork.IsBusy() AndAlso listUsr.Items.Count > 0 Then

scriptingWork.RunWorkerAsync()

End If

End Sub

Non e’ assolutamente nulla di trascendentale. Bene: su XP SP2 (up-to-date) non voleva saperne di funzionare ma copiato sul server Windows 2003 funzionava!!!

August 20, 2007

Un film lungo… 8171 anni

MySky integer unsigned problemStavo guardando Kill Bill vol. 2 che mi ero registrato qualche tempo fa su MySky (che - a mio avviso - e’ una soluzione a dir poco eccezionale e senza cui oggi non penso che potrei guardare i film che mi interessano) e sono incappato in una curiosa situazione (dovrei segnalarlo allo staff tecnico di SKY, ma ancora non ne ho avuto tempo). Mettendo in pausa il film mi sono accorto che alla fine mancava la bellezza di… 8171 anni!! Gloria all’utilizzo dei numeri interi :)

Ad ogni modo sembra che il problema si verifichi quando la capacita’ del disco scende sotto il 30% (in effetti credo ci sia anche un qualche problema di frammentazione ma non ho mai indagato sulla cosa).

June 21, 2007

Visioni IT: continuiamo ad integrare il Help Desk

Questa cosa l’avevo gia’ pensata piu’ di una volta. All’apparenza e’ una cosa ovvia in un sistema di gestione delle chiamate ma poiche’ il sistema di tracking del Help Desk l’ho sviluppato io, per un motivo o per un altro, non e’ mai stato implementato (essenzialmente mancanza di tempo e/o risorse per poterlo fare). A carattere generale ho deciso, per una vasta serie di motivi, di sviluppare l’applicazione su un server Microsoft Windows 2003, IIS, un database MySQL e PHP 5. I motivi di questa scelta saranno sicuramente motivo di una discussione più avanti :)
 
Il concetto di questa idea è piuttosto semplice: e se potessimo intercettare le telefonate che arrivano ai nostri interni (del supporto tecnico) per recuperarli quando andiamo a compilare i dati su una chiamata? Mi spiego meglio.
 
Attualmente le chiamate vengono gestite in modo manuale: un utente chiama, registriamo la chiamata, la categoria di guasto, il nome dell’utente e il suo recapito telefonico. Ma se il numero di telefono venisse direttamente dal centralino? Il nodo cardine di tutto questo e’ che so anche come fare la cosa.
 
Un utente chiama il supporto tecnico. Il telefono (malauguratamente) inizia a squillare. Il centralino fa partire una trap SNMP verso il sistema gestionale che, alla sua ricezione, carica i dati nel database. L’Operatore risponde al telefono e fa click sul hyperlink che gestisce le chiamate in arrivo. L’inserimento del record genera automaticamente una chiamata tecnica, ancora priva di informazioni supplementari. In questo modo, se tutti gli Operatori sono occupati, rimane comunque traccia delle chiamate in entrata.
 
L’Operatore risponde al telefono, e dall’elenco delle chiamate in ingresso sul Gestionale seleziona la chiamata che sta gestendo. La classifica, vi assegna una priorità e la chiamata passa in fase di elaborazione in meno di 30’’ (calcolando convenevoli come saluti e domande di rito sul tempo e la salute). Intanto si può procedere con l’analisi del problema e l’eventuale soluzione al telefono del medesimo, altrimenti rimane traccia di quelle che sono le attività ancora da fare (e quindi seguono il ciclo di vita normale di un caso di soluzione del problema). Qualora gli Operatori fossero tutti occupati a rispondere ad altre chiamate, oppure a lavorare su un problema generale, o fossero semplicemente in bagno, il sistema continua a raccogliere i numeri di telefono che possono essere richiamati quando il o gli Operatori ritornano alla propria postazione.
 
Ora, questo sistema può vedere alcuni vantaggi ed alcuni svantaggi. Iniziando dagli svantaggi, la compilazione dei fari elementi delle form potrebbero essere abbastanza seccanti, per cui la cosa si potrebbe ovviare con una serie di “bookmark” e dati preconfezionati al fine di ridurre le operazioni di immissione dati a pochi secondi. Personalmente, da un punto di vista sia organizzativo che tecnico, vedo solo questo come problema cruciale. I vantaggi invece mi sembrano enormi. Iniziamo dal fatto che tutte le chiamate entranti al helpdesk vengono registrate. Poiché si tratta di un sistema di gestione delle chiamate di assistenza, non abbiamo il problema della privacy (consideriamo anche che i vari Call Center fanno esattamente la stessa cosa anche in ambiti pubblici). Il sistema raccoglie la data e l’ora esatta della chiamata, col vantaggio di avere un punto certo di partenza della segnalazione (talvolta lasciato all’Operatore del HelpDesk, azione che va ad impattare molto su eventuali SLA e regolamenti interni per la soluzione dei problemi). In un ambiente geograficamente distribuito, la raccolta e il raggruppamento dei dati eseguibile direttamente sul database può portare alla generazione di report dettagliati e capillari sui costi di mantenimento e sforzi amministrativi per la soluzione dei problemi sui vari centri di costo, per non parlare del fatto che l’analisi dei dati (con opportuni report) può anche portare a fare previsioni e proiezioni nel futuro sui problemi e sulle necessità di una determinata sede.
 
Help Desk home made? Decisamente continuerei su questa linea.

June 5, 2007

Privacy & Sviluppo Web

Le attuali leggi sulla Privacy (e il buon senso) richiedono che lo sviluppo applicativo sia fatto in modo da tutelare l’accesso ai dati sensibili alle persone che effettivamente ne abbiano l’autorizzazione. Secondo alcune linee guida, lo sviluppo prevede che si creino sul database viste e query che, in base al livello utente, diano l’accesso a un determinato set di informazioni. Questo tipo di approccio, secondo me, è molto oneroso in termini di risorse e visti i tempi di sviluppo effettivamente a disposizione, non è facilmente perseguibile. Quello che vi voglio proporre qui è un metodo alternativo per sviluppare applicazioni web che rispondano a suddette esigenze in modo rapido.
 
L’applicazione utilizza PHP come linguaggio di programmazione di esempio tuttavia può essere applicato a qualsiasi altro linguaggio di programmazione. Le query SQL riportate sono di MySQL.
 
La prima fase di questo sviluppo dovrebbe consistere nello sviluppo di una forte serie di funzioni che realizzino le funzioni di autenticazione ed autorizzazione. Questo insieme di funzioni devono svolgere i compiti di seguito proposti. Assegnerò ad alcune funzioni dei nomi, in modo da poterle richiamare nel codice di esempio che vado proponendo.
 
Funzione di autenticazione
 
Questa funzionalità deve essere presente sempre. Non la si può omettere, deve supportare un meccanismo di controllo che verifichi l’esistenza delle credenziali e la loro correttezza, lo stato attivato o meno dell’account. A livello di codice applicativo questa funzione può essere omessa in quanto la gestione delle credenziali può essere delegata al Web Server (autenticazione di base, ecc.) poiché più facilmente gestibile ed integrabile con altri sistemi di autenticazione o single sign on (per es. IIS ed Active Directory) che sono più facilmente controllabili e dispongono già di un forte sistema di controllo dell’accounting utente (scadenza password, complessità, ecc.)
 
Funzione di gestione delle autorizzazioni
 
Questa a differenza della suddetta componente, invece, è indispensabile. La funzione assegna all’utente un “livello” di autorizzazione che, trasversalmente su tutta l’applicazione, fornisce all’utente accesso a determinate componenti o contenuti. La funzione caricherà in sessione (non in cookie!!!) i livelli di autorizzazione dell’utente che devono essere sempre accessibili. Al logon utente il set di credenziali fornito verrà quindi confrontato con il livello dell’utente, e il suo “token” di autorizzazione verrà salvato in sessione. Ogni volta che si andrà a pubblicare una componente (un’ancora, un record, anche una singola etichetta) il programma andrà a verificare se l’utente è autorizzato o meno ad accedere a quella informazione usando il “token” come metodo di confronto.
 
Come gestiamo l’accesso ai dati?
 
Supponiamo di avere una tabella anagrafiche strutturata così:
CREATE TABLE tbl_pazienti (
 ID_paziente INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
 nome_paziente VARCHAR(45) NULL,
 codice_fiscale CHAR(15) NULL,
 indirizzo VARCHAR(45) NULL,
 localita VARCHAR(255) NULL,
 provincia CHAR(2) NULL,
 stato CHAR(3) NULL DEFAULT “ITA”,
 telefono VARCHAR(20) NULL,
 codice_assistito CHAR(10) NULL,
 PRIMARY KEY(ID_paziente)
);
Secondo le linee guida, per ogni “livello” di autorizzazione dovremmo creare una vista che dia accesso solo ad una limitata componente di dati. A livello di codice, poi, dovremmo fare una serie di strutture di controllo che, in base al livello utente, carica la vista opportuna. L’impegno per la gestione dei permessi diventa onero, mentre l’aggiunta di un nuovo livello di autorizzazione richiederebbe l’intervento almeno di un DBA (se il codice è stato strutturato opportunamente).
 
Implementando il metodo descritto nel presente articolo, invece, andiamo a gestire tutto a livello applicativo. Attraverso un pannello di configurazione è possibile configurare i parametri di “autorizzazione”. Il processo di creazione di un nuovo livello di autorizzazione prevede i seguenti passaggi:
  1. Creazione del livello di autorizzazione
  2. Per ogni tabella andiamo a definire quale colonna l’utente può visualizzare e quale no (un valore booleano)
  3. Salviamo le modifiche
La suddetta operazione può essere svolta tranquillamente da qualsiasi utente che abbia le opportune credenziali di accesso al pannello amministrativo, e non deve assolutamente essere né un DBA, né un programmatore. A livello di codice invece? Tutto esattamente uguale. Vediamo come.
 
Partendo dalla SELECT che interroga il database, supponiamo di caricare il record di un determinato paziente.
SELECT t.nome_paziente, t.codice_fiscale, t.indirizzo, t.localita,
       t.provincia, t.stato, t.telefono, t.codice_assistito
FROM tbl_pazienti t
WHERE t.ID_paziente = 25
LIMIT 1;
La query restituisce un record solo con i dati anagrafici del paziente. Ora vediamo il codice applicativo.
 
La regola del RAD (Rapid Application Development) dice che per visualizzare i dati dobbiamo fare una struttura del tipo:
$q = “SELECT…..”;
$r = mysql_query( $q );
$data = mysql_fetch_array( $r );
 
# Altro codice
 
print( $data[ “nome_paziente” ] );
Non vogliamo stravolgere la regola dello sviluppo rapido delle applicazioni, anzi, lo vogliamo mantenere. Allora sostituiamo solo una sola funzione di tutto il set suddetto: la funzione print().
 
La nostra nuova funzione (che chiamerò “getElement” ) non fa altro che fare l’output del contenuto di un elemento $data, tuttavia prima di farlo, verifica se l’utente ha il permesso di visualizzare quel elemento. Secondo il suddetto esempio, pertanto, avremo che il codice da noi scritto sarà più simile al seguente esempio:
$sql = “SELECT ….”;
$obj->query( $sql );
 
# Altro codice
 
print $obj->getElement( “nome_paziente” );
Conclusioni
 
Il vantaggio di questo metodo di programmazione è che lo sviluppatore può sviluppare le applicazioni in modo rapido, senza più curarsi del concetto di autorizzazione. Il sistema descritto può essere applicato a qualsiasi elemento del programma come etichette, elementi dei form, ancore, ecc. Sviluppando delle guide all’interno dell’area di amministrazione si effettua una completa spaccatura tra Utente Finale che deve fruire di un’applicazione, e il gruppo di sviluppo che invece deve intervenire su di essa aggiungendo nuove funzionalità. Quando un utente finale necessita di modificare un livello di autorizzazione, con il sistema proposto è sufficiente che si rivolga alla persona che si occupa della gestione dei livelli la quale, normalmente, è una persona interna che conosce bene l’ottica aziendale. Se usassimo delle viste, invece, ci troveremmo a dover chiamare un DBA o lo sviluppatore, con la logica conseguenza di dover attendere un periodo di tempo più lungo per avere la modifica (e possibilmente anche dei bug poiché la modifica è eseguita sul codice).
 
Esistono degli aspetti sulla sicurezza e sulla privacy (questo esempio è legato al mondo sanitario che mi affascina molto ultimamente) che non ho contemplato nell’articolo poiché sono principalmente argomenti sistemistici. Questi elementi sono la comunicazione tra database e application server, e tra application server e client di rete, la crittografia dei dati sui dischi dei database, e l’eventuale crittografia dei dati all’interno delle tabelle dei database. Magari saranno argomento di un altro articolo :)