progettazione e sviluppo di un framework di supporto in ambiente aziendale su tecnologia share point...
DESCRIPTION
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010TRANSCRIPT
UNIVERSITÀ DEGLI STUDI DI TRIESTE
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK
DI SUPPORTO IN AMBIENTE AZIENDALE SU
TECNOLOGIA SHARE POINT SERVER 2010
Dipartimento di Ingegneria e Architettura
Corso di Laurea Magistrale in Ingegneria Informatica
Laureando: Relatore:
DOTT. ALEX RONCI DOTT. ING. MAURIZIO FERMEGLIA
Correlatore:
DOTT. DARIO SOTTANA
ANNO ACCADEMICO 2013 - 2014
2
Ad Ornella, Antonello e Thomas
3
1 Introduzione
La tesi proposta all’interno di questo documento tratta la progettazione e la programmazione
di una struttura di appoggio per gli sviluppatori definita come framework di sviluppo utile alla
generazione di un sistema informativo in ambiente CMS (Content Management System)
Microsoft SharePoint Server 2010 con cui dare l’opportunità di esulare dall’utilizzo base della
struttura di workflow, un modello per la pianifica strutturata di processi programmati,
proposta ed implementata dall’azienda di Redmond.
Commisionataria del progetto è l’azienda Reply SpA – Cluster di Trieste.
L’interesse dell’azienda è quella di avere una struttura più flessibile rispetto quella proposta
dalla Microsoft: difatti, come descritta sul loro sito ufficiale, “Workflow is sometimes described
as a series of tasks that produce an outcome. In the context of Microsoft SharePoint Products
and Technologies, workflow is defined more narrowly as the automated movement of
documents or items through a sequence of actions or tasks that are related to a business
process”; a quanto si evince, la possibilità di far fluire il materiale a disposizione in maniera
non lineare non è contemplata nelle intenzioni originali della piattaforma SharePoint.
Questo fatto ci porta ad optare per una soluzione custom che permetta uno scorrere libero
lungo tutte le fasi del processo produttivo che si andrà ad implementare nella site collection di
interesse. L’obiettivo della tesi dunque risulterà implementare, all’interno di una feature
adeguabile ad ogni circostanza similare, un workflow personalizzato a fasi, accompagnato da
tutti quei metodi, form ed elementi che possano risultare utili ad un corretto e semplificato
sviluppo di una site collection nell’ambiente di riferimento per uno sviluppatore futuro.
L’importanza non sarà dunque solamente quella di fornire un prodotto che permetta di
scorrere nel processo produttivo, ma che funga primariamente da framework orientato ad
agevolare la scrittura di codice da parte di un programmatore che andrà a referenziare tale
libreria nella sua soluzione, in modo tale che non debba perdere tempo nello sviluppo di
articolati metodi ripetitivi, come possano essere quelli di un passaggio fase, un ritorno ad una
fase precedente, alla gestione dei permessi od alla creazione automatizzata di elenchi di
servizio interno.
4
Pur nella vastità del progetto, gli elementi che verranno trattati all’interno di questa tesi
saranno alcuni di questa libreria, con un occhio particolare su:
a) Metodi e classi per lo sviluppo delle funzioni di utility: lo sviluppo di tutte quelle
funzionalità base da fornire allo sviluppatore per agevolare il compito di scrittura del
codice. Fornire una gamma di metodi più e più volte richiamati all’interno
dell’ambiente di sviluppo può portare ad un grosso vantaggio in termini di tempo, e di
uniformità di invocazione e gestione di accessi, creazione, modifica delle strutture
fornite da Sharepoint.
b) Sviluppo logico del workflow: lo sviluppo di una soluzione custom per lo scorrimento in
avanti ed indietro nel processo produttivo, tenendo sotto controllo la gestione e
controllo dei permessi sugli oggetti coinvolti. Fornire una gestione logica e
standardizzata dell’applicazione è importante per semplificare al massimo il lavoro
dello sviluppatore che utilizzerà tale framework, e dunque è fondamentale sviluppare
le proprie componenti in maniera che siano comprensibili ed adattabili alle più svariate
situazioni, rendendole il più possibile generiche.
c) Esempi: A completamento del progetto, verranno presentati alcuni casi di
implementazione di quello che è stato sviluppato nei punti precedenti, in modo tale da
rendere l’idea di come produttivamente possano essere utili le librerie sviluppate.
Ovviamente gli elementi che verranno implementati all’interno delle libraries sono
possibilmente molti di più, ma probabilmente possono risultare meno interessanti di quelli che
sono stati citati, perché meno personalizzati oppure meno salienti rispetto l’obiettivo verso cui
protende la tesi stessa, ma sono utili per poter far funzionare appieno tale feature.
1.1 Perché Microsoft SharePoint Server 2010
La scelta di approfondire il progetto in un ambiente professionale come quello di SharePoint
Server 2010, piuttosto che la corrispettiva piattaforma Foundation oppure un utilizzo più
visuale come quello fornito da SharePoint Designer, è dovuta al fatto di poter operare su di un
prodotto più approfonditamente modificabile ed alterabile, in cui un’interfaccia a codice (nel
caso di SharePoint C#) possa permettere di intervenire più in profondità sulle strutture di
interesse.
5
Da un breve confronto ed analisi dei pro e contro dei vari ambienti di sviluppo, difatti, si può
ritenere che la possibilità di personalizzazione di SharePoint può essere così tracciata: se con
un utilizzo base, direttamente da interfaccia web, uno sviluppatore (o meglio, in questo caso
sarebbe più corretto indicare un utente “collaboratore”) potrebbe andare a caratterizzare
approssimativamente un cinquanta per cento delle potenzialità della Site Collection
sviluppata, e con il crescere delle capacità e conoscenze ad un circa sessantacinque, solo
approdando in un ambiente adeguato (come per esempio SharePoint Designer) potrebbe
ottenere dei risultati che si avvicinino al massimo del potenziale. Servono assolutamente degli
ambienti di sviluppo (IDE) adeguati (ed in questo caso la migliore è quella fornita direttamente
di Microsoft con Visual Studio) e una profonda conoscenza del linguaggio di sviluppo, in modo
tale da avvicinarsi prepotentemente alla completa gestione delle potenzialità del CMS.
Questo è l’obiettivo ultimo di tale tesi: avere un prodotto più possibilmente performante e
generico che possa essere integrato nella maggior parte dei progetti di interesse dell’azienda
commisionataria, in modo tale da poter agevolare e alleggerire il carico lavorativo dello
sviluppatore, fornendo un framework di supporto nelle più comuni necessità di integrazione
tra l’ambiente default fornito da Microsoft e quello personalizzato e maggiormente pertinente
al tipo di attività svolte dall’azienda.
Il documento qui presente risulterà, in conclusione, diviso in tre parti fondamentali:
Nella prima sezione, verrà trattato il nuovo sistema di workflow, descrivendone le
caratteristiche mantenute dalla versione Microsoft e le soluzioni custom proposte in
questa tesi, tracciandone principalmente la sua struttura logica e dandone una prima
applicazione in produzione caratterizzando le possibili strutture da implementare;
La seconda sezione, quella più corposa, andrà a trattare la composizione della library di
metodi che andrà a far da fondamenta per il framework obiettivo di tesi, descrivendone
l’architettura e le funzionalità attribuitele, e descritti i metodi forniti al suo interno
(con, in alcuni casi, approfondimenti sul flusso logico delle operazioni svolte);
La terza sezione, invece, andrà a fornire un esempio di applicazione delle aree
precedenti, con un’analisi del connubio delle varie fasi operative del workflow ed il
framework stesso, rendendo così pratica l’applicazione della teoria proposta nei
capitoli precedenti
6
Nella parte finale del documento, invece, verranno indicate le possibili espansioni del
framework sviluppato, e nelle appendici verranno approfonditi alcuni interessanti temi che
vadano a motivare o a esplicare alcune operazioni trattate durante l’intero sviluppo del
testo.
7
2 Workflow
La prima parte del progetto è quella preposta ad analizzare e sviluppare una struttura di
workflow che vada a sopperire alle mancanze, dal punto di vista dell’azienda
commissionataria, di quella proposta da Microsoft.
2.1 Breve definizione
Il workflow1 è la descrizione di una sequenza di operazioni di un lavoro attribuito ad una
persona od ad un gruppo, all’interno di un meccanismo di step che si susseguono senza ritardi
uno dopo l’altro, e spesso viene trattato come un’astrazione del lavoro reale, o come
rappresentazione di quest’ultimo.
Più correttamente, quello che viene esplicitato da noi è quello che viene definito Workflow
Management System, un sistema informatico che gestisce ed organizza una serie di tasks per
restituire in uscita il risultato del processo produttivo, anche se risulta più semplice definirlo
workflow.
Gli elementi da tenere in considerazione all’interno di un’attività di un workflow sono:
1. Input: tutte quelle che sono le informazioni necessarie al completamento dello step;
2. Gli algoritmi e le azioni da svolgere, a livello umano o a livello macchina, per
completare lo step;
3. Output: tutte quelle informazioni che verranno passate al completamento dello step
stesso.
2.2 Workflow in SharePoint
Rispettando le linee guida che vanno a definire il flusso, SharePoint2 propone delle soluzioni
lineari, orientate all’organizzazione efficace di ruoli e task attivi all’interno del processo, in
modo tale da garantire la riduzione ai minimi termini di delay durante i passaggi di consegne,
adattandosi al genere di flusso dati richiesto all’interno dell’organizzazione interessata.
Come rimarcato anche dalla definizione, il workflow mantiene una struttura lineare e
unidirezionale, come esplicitato dai flussi proposti di default in SharePoint:
1 https://en.wikipedia.org/wiki/Workflow
2 http://technet.microsoft.com/library/cc263148(office.14).aspx#WFlowOverview
8
Raccolta commenti e suggerimenti;
Approvazione;
Approvazione dell’eliminazione;
Raccolta firme;
Tre fasi;
Gestione traduzioni;
Gestione problemi.
Vi è la possibilità di introdurre dei workflow dichiarativi (quelli descritti in precedenza) oppure
compilati, con l’aggiunta di codice personalizzato; tutti conducono ad un flusso ordinato di
dati.
2.3 Requisiti
Il tipo di workflow richiesto in questo processo ha delle peculiarità:
Possibilità di scorrimento all’indietro nel flusso, in opportuni casi, svincolandosi dalla
rigidità del workflow classico;
Organizzazione dei task in macrofasi, di cui è possibile modificarne i contenuti nel
momento in cui vi si trova al suo interno.
Per l’implementazione, viene lasciata totale libertà di scelta delle strutture su cui far poggiare
il flusso in SharePoint, senza richiedere vincoli di utilizzo di DBMS particolari o strutture
particolari.
Inoltre, viene richiesto di consegnare tutta una serie di funzionalità, metodi che ne
permettano un’implementazione efficace all’interno del CMS.
9
Figura 1 - Task
2.4 Specifiche
I due requisiti proposti sono legati l’un l’altro, poiché possono permettermi di operare
all’interno di un ambiente di workflow pur modificandone parzialmente la logica.
Il concetto di task è considerabile come un insieme atomico di azioni da compiere per portare
un item dallo stato A allo stato B
E le modifiche apportate, giunti nello stato B, risultano permanenti, senza permettere dunque
la possibilità di ritornare ad A.
Le modifiche da proporre sono dunque legate alla gestione del task ed al susseguirsi logico
delle attività da svolgere all’interno del workflow: si è scelto di procedere secondo le logiche
descritte in seguito per implementare queste modifiche.
2.4.1 Gestione delle macrofasi
Se si vogliono introdurre delle macrofasi, o macro attività, all’interno del workflow,
rimandendo coerenti con il suo funzionamento logico, c’è la necessità di stravolgere il
concetto di task in quanto tale.
Il task non può essere trattato come unità atomica, ma come sequenza di microtasks interni
che si susseguono, e comunicanti tra loro i contenuti raccolti nella loro azione.
Se ne volessimo fare una raffigurazione grafica, questo sarebbe descrivibile in tal maniera:
Figura 2 - Macro Task
10
La struttura avrebbe dunque:
Ingresso al task dall’esterno (freccia arancione in ingresso);
Uscita dal task sia a livello logico (freccia arancione da Task C), sia a livello di dati
(freccia gialla da Dati), con unica uscita output.
preconfigurandosi, almeno alla visione esterna, con la struttura di una classica attività di
workflow.
Le modifiche sostanziali sono all’interno:
I dati vengono divisi dalle attività;
Scindendo contenuti e processi, posso suddividere le operazioni in micro-attività,
mantenendo condivisi i contenuti fino a quel momento inseriti;
Ogni micro attività avrà a disposizione tutti i dati raccolti nei micro task precedenti,
permettendone l’edit di questi, oltre a quelli di pertinenza della fase in questione;
Su ogni micro task, essendo considerati essi stessi task, avranno diritto di azione ruoli
diversi (se necessario);
Il flusso descritto dalle frecce arancioni traccia il percorso dello stato del workflow,
mantenendone l’ordine logico anche all’interno del macro task e marcandone la struttura,
mentre quelle gialle tracciano il flusso dei dati raccolti, mostrando come i contenuti siano
condivisi all’interno della macro fase, e siano accessibili in lettura e scrittura a seconda dello
step in cui vi si trovi.
L’attività opera in tal maniera:
1. Il workflow entra nel macro task, come se si trattasse di una comune attività;
2. Vengono definiti i ruoli del primo micro task;
3. L’utente incaricato opera sui dati che può operare nello step in cui si trova;
4. Completata l’operazione, vengono spostati i dati all’interno dell’area condivisa e
vengono trasferiti i ruoli all’utente di pertinenza;
5. L’utente subentrante ha la possibilità di operare sui dati vecchi sia su quelli inerenti al
suo step;
6. Completata l’operazione, si reitera da 4, finchè non si completano tutti gli step interni;
11
7. Arrivati all’ultimo step, escono sia i dati che lo stato di fase, in modo tale da restituire
un valore unico all’attività successiva.
Il task così definito può andare a sostituire logicamente quello classico all’interno del flusso,
poiché non va ad intaccarne la teoria alla base: se ne mantiene l’orientamento, ma ci permette
di operare in istanti diversi su dati che possono essere già stati inseriti in precedenza, senza
dover abortire il processo.
Il workflow assumerà dunque questa possibile nuova forma:
2.4.2 Gestione del rollback di uno step
Secondo passo da analizzare è quello del ritorno ad uno step precedente, concetto non
contemplato nella teoria dei workflow.
Le problematiche di questo tipo di processo sono dovute a:
Conservazione dello stato del task: se torno indietro, dove mi trovo?
Conservazione dei dati: se torno indietro, i dati inseriti in step successivi dove vanno a
finire?
Permessi: se torno indietro, ho ancora accesso agli step successivi, o solamente alla
fase in cui si è tornati?
Ruoli: chi ha la possibilità di fare il rollback?
Dalla discussione di queste tematiche possiamo ottenere una possibile risposta alla richiesta.
Figura 3 - Esempio di Workflow personalizzato
12
2.4.2.1 Stato del task L’operazione di rollback non deve essere evidente ad una visione esterna del flusso, questo
per i soliti motivi asseriti nella teoria dei workflow.
Quindi deduciamo che la risposta sia: se vi è una rollback, per il workflow devo trovarmi
comunque nello stato precedente, così da ovviare a problematiche di gestione e
comprensione del flusso stesso.
2.4.2.2 Stato dei dati La conservazione dei dati nel caso di rollback è di articolata gestione, poiché il passaggio da
una fase N ad una N-1 comporta
1. Cambiamento dei dati ricevuti in input da N-1;
2. Possibile cambiamento dei dati in input da N;
3. Possibile incompatibilità dei dati inseriti in precedenza in N con i nuovi di N-1
Proponiamo qualche esempio pratico:
In fase N-1 ho inserito un documento, e i dati al suo interno determinato le operazioni
della fase N; se torno in fase N-1, ho la possibilità di sostituire tale file, e di conseguenza
condizionare le operazioni di N;
Nella fase N respingo i contenuti di N-1, consentendo, con il rollback, la sostituzione di
questi ultimi. Avrebbe senso conservare i dati (negativi) di N tornando in fase N-1?
In N eseguo alcune operazioni, ma verifico l’incompletezza (o l’inesattezza) dei dati
passati da N-1; se le operazioni svolte in N non sono toccate dalle correzioni, ha senso
non conservare i dati fino a lì raccolti?
Se in N-1 ho la possibilità di fare un rollback anch’esso per N-2, dovrei avere condizioni
di verifica tali da poter verificare che le sostituzioni possibili in N-2 non abbiano effetto
su N-1 e dunque su N.
L’elemento di cui tenere primariamente conto dunque è la possibilità di intaccare la
correttezza e la consistenza dei dati raccolti dallo step N-m (con m numero di rollback) a N
(fase effettivamente raggiunta).
Dunque la risposta presa in considerazione è: non risulta efficace conservare i dati delle fasi
successive se vi è stato un rollback, per evitare rischi di correttezza dei dati già acquisiti. Le
13
occasioni di avere dei dati non condizionanti, all’interno di workflow, sono molto poche,
dunque è difficile che non vi sia incidenza di un task in quello successivo.
2.4.2.3 Permessi La possibilità di operare indistintamente tra più fasi successive può creare dei problemi similari
a quelli descritti nel punto precedente: la correttezza del dato resta comunque un cardine di
qualsiasi processo informatico, e consentire operazioni parallele su contenuti che possono
condizionarsi vicendevolmente può essere pericoloso.
Dunque la possibile soluzione è quella di non concedere l’accesso alle operazioni consentite in
una fase N, nel caso in cui si torni in una N-1, per le stesse motivazioni date nel paragrafo
precedente.
2.4.2.4 Ruoli nel rollback Altro frangente da tenere in considerazione è il tipo di utenza che può operare il rollback del
task. Questo deve coincidere con l’utente stesso che ha diritto di operare sul task stesso
oppure posso concedere dei permessi speciali ad un utente esterno e sorvegliante il
workflow?
Consentire l’interazione di utenze esterne all’interno di un task di non propria competenza
andrebbe in contrasto con il flusso previsto nella teoria dei flussi: l’utenza opera unicamente
sui task di propria competenza.
Si possono dunque generare dei task di approvazione dei dati, in modo tale da scindere il
rollback dal concetto di approvazione del dato inserito da altre utenze.
La risposta a quest’ultimo punto può essere quindi negativa, non consentendo utenti con
poteri di rollback esterni a quelli già aventi diritto di processo su di un determinato task.
2.4.3 Definizione delle specifiche
Dall’analisi dei punti precedenti, la specifica che ne possiamo trarre fuori avrà questi vincoli:
Il rollback verrà introdotto unicamente all’interno dei macro task descritti in 2.4.1:
come illustrato dalle frecce rosse, il flusso all’indietro all’interno del macrotask non
genera problemi, per via dei dati condivisi e del non variare dello stato del flusso
complessivo del workflow.
14
Figura 4 - Rollback in Macrotask
Il rollback non sarà consentito a cavallo di task non appartenenti allo stesso macro
task, per non intaccare la consistenza dei dati;
Il rollback annullerà tutti i dati inseriti nelle fasi successive a quelle in cui ci si trova, per
evitare problemi di consistenza dei dati;
Il rollback inibirà l’accesso a tutte le operazioni di fasi successive a quella in cui ci si
trova: se torno dal task C al task B, non avrò modo di operare sul task C finchè non avrò
nuovamente concluso il task B;
Il rollback non sarà consentito ad utenze che siano esterne a quelle che ne hanno
diritto; non è contemplato un utente supervisore che condizioni il flusso.
Figura 5 - Rollback tra task diversi
Annulla Dati di fase
Figura 6 - Eliminazione dati con Rollback
15
Il flusso conserverà tutti i suoi crismi originali, e il nostro lavoro dunque si concentrerà sulla
gestione dei macro task e sulla rispettiva strutturazione in ambiente SharePoint, esulando
dalla struttura di default proposta da Microsoft.
2.4.4 Specifiche accessorie
Oltre a comprendere quali siano le soluzioni per i due requisiti, è importante definire e
comprendere quali siano le specifiche di contorno utili al progetto:
1. Interfacce che permettano la visione globale e precisa di workflow ed istanze di queste;
2. Nel caso di istanze di workflow, elementi di gestione di flusso tra le varie fasi, sia in caso
di passaggio tra fasi interne ad un macrotask, sia nel caso di flusso da un task ad un
altro, quali ad esempio pulsanti complementari a quelli di default;
3. Possibilità di visionare ed editare i dati di fasi precedenti interne al proprio macrotask
senza che questi si mescolino / non siano evidenti all’interno del task di propria
competenza. In tal maniera abbiamo una descrizione a tutto tondo di quello che ci
servirà per definire e rendere il workflow comprensibile e gestibile all’utente finale.
Task completato Task in esecuzione
Rollback Task C
A
B
C
A
B
C
A
B
C
Task A completato
Completo task B
Task non eseguibile
Figura 7 - Inibizione di accesso a dati futuri con Rollback
16
2.5 Progettazione
Basilare è scegliere come organizzare il workflow, definendo su quale delle possibili strutture
dati gestire il flusso. Allora sarà da specificare come implementare lo scorrimento tra le fasi e
tutto ciò che va a circondare questi processi.
2.5.1 Gestione dei dati nelle macrofasi
Lo step è trovare una struttura logica che ci permetta di gestire la condivisione delle
informazioni tra task successivi ed appartenenti alla stessa macrofase. Non è possibile gestire
nelle modalità proposte da un workflow classico, poiché i dati caricati in precedenza sarebbero
accessibili solo per approvazione, e non in edit (tornando cioè alla conformazione di task
distinti e non aggregati).
L’ipotesi che si va a proporre dunque contempla una gestione condivisa dei dati stessi, tramite
un insieme (ipotizzabile in forma tabulare) aggregato di informazioni suddiviso per sottoaree,
accessibili a seconda del task in cui ci si trova.
Con una rappresentazione grafica, si può ipotizzare un frammento all’interno di una macrofase
in questo modo descritto:
In tale modo l’utente del task avrà almeno accesso in lettura ai dati delle fasi precedenti, se
non addirittura in scrittura (dipende dal ruolo dell’utente coinvolto), potendo dunque gestire e
motivare il rollback (ad esempio, correzione dei dati inseriti in precedenza), ed allo stesso
tempo operare su dati inseriti in precedenza senza arrecare inconsistenza nei dati.
Dati
Task A Dati
Task B
Dati Task C
Task A Task B Task C
Figura 8 - Dati condivisi in macrotask
17
2.6 Scelta della struttura dati
La struttura, tra quelle disponibili in SharePoint, più similare a quella proposta, anche se può sembrar banale, è quella della lista. Questo perché:
È un insieme ordinato di oggetti in cui si può accedere alle varie colonne in modo
guidato, tramite le form;
Permette di avere un aggregato dei dati della macrofase, associato in modo univoco ad
un item, che è il nostro flusso;
Posso relazionare più liste (e dunque più macro task) tra loro inserendo un
identificativo univoco e condiviso tra le varie liste, in modo tale da tenere traccia
dell’evoluzione del flusso.
Posso inserire un parametro di fase, che mi identifichi in quale stato si trovi il
macrotask al momento del salvataggio, in modo tale da poter gestire di conseguenza i
permessi associati all’item.
Scegliere un’altra struttura, come ad esempio quella della Document Library, rendere il tutto
decisamente più complicato a livello di organizzazione:
Sarebbe da organizzare una folder della DL per ogni flusso interessato, e le relative
subfolder create ad ogni passaggio di macrotask, cosa che invece con un insieme di
liste (già definito) porterebbe alla sola aggiunta di un item con identificativo univoco
già creato;
Problemi sui permessi: ogni volta che creo una cartella dovrei configurare i permessi su
essa e poi su tutti i suoi contenuti, non avendo un parametro di controllo facilmente
condivisibile;
Problemi nella ricerca: dovendo attingere a delle cartelle, non ho la certezza di avere i
dati di cui sono interessato (potrebbero essere in eccesso o mancarne alcuni);
Problemi nel confronto dei dati: dovendo pescare da folder distinte, dovrei fare
un’analisi gerarchica all’interno di queste, verificando fino a che punto si sia giunti, per
poi raccogliere i dati; nel caso di una lista, vedo direttamente tramite una view quello
che mi interessa;
Gestione dei requisiti: Organizzo delle subfolder nelle subfolders? Avrei dei problemi a
sul piano del macrotask (i documenti non sarebbero condivisi, aprendo criticità a livello
18
di permessi). Organizzo tutto in una cartella comune? Avrei problematiche nella
distinzione dei file nelle varie microfasi;
Allo stesso modo, l’introduzione forzata di una struttura come i Document Set risulterebbe
maggiormente articolata (la banale installazione della feature associata costringerebbe ad
avere una site collection compatibile con quest’ultima) e non così efficace rispetto a quelli che
potrebbero essere i profitti: anche in questo caso ci troveremmo di fronte ad una struttura
atta a gestire documenti, non tanto a dati, riportandoci ai problemi definiti per la Document
Library.
Dunque, la strutturazione del workflow a macrofasi tramite liste risulta essere la soluzione più
efficace e completa per le nostre finalità: potremo apprezzare nei capitoli successivi come
questa via risulti adeguata.
19
3 Library SharePoint Utilities La seconda sezione del nostro progetto va a trattare il package che va a fornire le funzioni di
estensione più comuni per il tipo di progetti creati nell’azienda, e di appoggio al workflow
trattato nel capitolo precedente.
L’obiettivo primario è quello di fornire metodi utili ed efficaci al futuro programmatore in
modo tale che non debba scrivere del codice ripetuto, ripetitivo e spesso utilizzato all’interno
di un qualsiasi progetto.
Rispettando un concetto di chiarezza e semplicità all’interno del package, è importante anche
suddividere il prodotto sin dall’interno in feature, per mostrarne le diverse funzionalità e
permetterne l’utilizzo distinto a seconda dei casi.
Essendo un modulo di generics, è molto utile poter far scegliere al programmatore quali
funzionalità importare all’interno del proprio progetto, consentendo una scelta che non vada
ad inibire l’utilizzo di una o l’altra funzionalità. Oltretutto, la creazione di un numero maggiore
di feature consente una migliore gestione del debugging, poiché rende possibile ridurre le
problematiche ad un pacchetto più piccolo e più facilmente controllabile.
3.1 Requisiti
Il prodotto, in questa parte del progetto, deve soddisfare le richieste del workflow, dunque
consentire la gestione di:
Gruppi Utenti
Document Libraries
Liste di Configurazione
Elenchi
A cui, inoltre, associare la configurazione di WebPages all’interno dell’ambiente SharePoint, la
gestione degli accessi in modalità di manutenzione della piattaforma in utilizzo, e fornire tutti i
possibili metodi di supporto per un corretto funzionamento dei metodi richiesti.
20
3.2 Analisi funzionale
L’organizzazione logica della solution è già descritta dalle specifiche. Si necessita dunque di
due features separate, pur appartenenti allo stesso prodotto, per lo sviluppo del software e
per la gestione della manutenzione della site collection.
Per l’area di sviluppo, i requisiti indicano aree di sviluppo (sei) distinte tra di loro: la soluzione
più ovvia e mantenere questa configurazione pure all’interno della feature, consegnando una
classe per ogni tipologia di componente da implementare.
Si è dunque andati a definire sei classi che si distinguano per i metodi forniti:
1. DocLib per la gestione delle document libraries;
2. Groups per la configurazione dei gruppi;
3. KeyValList per le liste di configurazione;
4. Lists per la creazione di liste;
5. Mailer per fornire i servizi di mail al workflow;
6. PubManager per le pagine di pubblicazione da interfaccia
A questi dunque sono stati associati quei metodi comuni e necessari in ogni loro situazione.
Primariamente sono state dunque considerate 4 classi accessorie, che vanno a vertere su due
tematiche distinte, le security e il logging, e importate con queste modalità:
Figura 9 - Strutturazione funzionale della library
21
Il principio alla base delle classi accessorie si mantiene lo stesso di quello utilizzato nelle altre
classi: assegnarne una per categoria di funzionalità permette di distinguere immediatamente
ciò che viene fornito, semplificando allo sviluppatore la comprensione della struttura a
disposizione.
Per l’area di manutenzione, invece, i requisiti indicano una sezione di controllo degli accessi
alle operazioni disponibili.
L’idea proposta è quella di introdurre un prefiltraggio alle pagine a cui accedere, nel caso in cui
la feature sia attivata.
Proporre dei metodi, in questo caso, può risultare inefficace, poiché sarebbe poi da trovare
delle modalità per far passare tutte le pagine in prefiltraggio per questi, costringendo gli
sviluppatori ad inserire una chiamata al metodo in un qualsiasi Page Load, non sempre
disponibile oltretutto.
Si può preferire dunque la creazione di un ascx che funge in forma delagata all’apertura di ogni
pagina, così da inserire un controllo in questo preciso istante: questo va ad alleggerire il carico
sullo sviluppatore, che può completamente dimenticarsi la gestione di tale frangente, ed
occuparsi unicamente della scrittura del codice inerente alle funzionalità della pagina di
interesse.
Questa feature dunque sarà configurata in modo tale da fornire al solo gestore della site
collection ed agli amministratori la possibilità di attivare questa funzione (anche perché
sarebbero gli unici interessati ad averne accesso), e dunque attivabile per via interfaccia a
seconda della situazione.
Quello che si va ad ottenere, e che andremo a descrivere in seguito, è dunque una struttura
con due feature, le Utilities e la BlockUsers, attivabili in maniera distinta e indipendenti l’una
dall’altra, cosicchè ogni site collection abbia la possibilità di scegliere se attivare o meno tali
funzionalità fornite.
3.3 Feature Utilities
La prima feature sviluppata comprendere gli effettivi metodi di utilities che vanno a soddisfare
i requisiti di questa porzione di progetto.
22
3.3.1 Classi
3.3.1.1 DocLib La classe DocLib contiene quei metodi che vanno ad essere di supporto alla generazione delle
Document Libraries di nostro interesse. Al suo interno sono stati sviluppati, al momento, 5
metodi “principali”, con alcuni metodi accessori di controllo.
3.3.1.1.1 SPList Create Questo metodo va a generare una Document Library all’interno del site di interesse. Ha come
parametri di input questi argomenti:
o SPWeb web: è l’url del WebSite di interesse
o String name: è il nome da associare alla Document Library
o String description: è la descrizione da associare alla Document Library
o Boolean? displayOnQuickLaunch: è il valore di controllo per far visualizzare la
Document Library sulla Quick Launch Bar del WebSite.
Il diagramma di flusso del metodo è molto semplice:
Figura 10 - Flusso SPList Create
23
Il percorso illustra come gli argomenti di input influiscano direttamente sul procedere dello
stesso. Importante è avere definiti entrambi i parametri per eseguirne correttamente il list.add
all’interno del WebSite, che va a restituire la GUID della lista creata, su cui poi poter
configurare la property di visibilità nella quickLaunch.
Il list ed il web Update vanno a consolidare le modifiche svolte, a chiusura del metodo,
restituendoci la lista stessa come output.
Nel caso di malfunzionamento, il metodo va in catch e da un log di report.
3.3.1.1.2 Void MoveAttFile Questo metodo permette il trasferimento di un documento da una Document Library ad
un’altra. Gli argomenti in input sono:
o SPWeb web;
o String listName: è il nome della Document Library da cui attingere;
o String oldStringUrl: è il percorso da dove proviene il documento da trasferire;
o String fileName: è il nome del file da trasferire;
o List<String> folderListLevel: è l’elenco delle folder del percorso per giungere alla folder
in cui spostare il documento;
o Boolean forceElevatedPrivileges: permette, a seconda del valore settato, di operare o
no con i permessi da amministratore;
o Out String url: è l’url di uscita del file trasferito
Il metodo va a richiamarne un altro omonimo, con gli stessi input (tranne la gestione dei
permessi elevati), che esegue il processo vero e proprio:
1. In un boolean viene salvato lo stato dell’AllowUnsafeUpdates;
2. Lo stato del web.AllowUnsafeUpdates viene settato a false, per poter operare senza
problemi questo processo di trasferimento;
3. Viene richiamato il metodo EnsureFolders per verificare che il path assegnato sia
realmente esistente, dandocene l’url (lo approfondiremo nella descrizione del metodo
stesso);
4. Viene recuperato l’SPFile tramite l’oldFileUrl;
24
Figura 11 - Flusso insertFile
5. Tramite il metodo dell’oggetto MoveTo, quest’ultimo viene spostato nel nuovo path
con il fileName assegnato;
6. Viene generato l’url definitivo, che verrà poi restituito come output del metodo;
7. Viene ripristinato lo stato iniziale dell’AllowUnsafeUpdates.
Anche in questo caso viene configurato un try / catch in modo tale che possa intercettare gli
errori di inserimento dei file nelle varie cartelle, verificando l’unicità di tale documento e
l’effettiva trasferibilità dello stesso.
3.3.1.1.3 Void InsertFile
In maniera similare al precedente, questo metodo va a creare un file all’interno della
Document Library di interesse. Gli argomenti del metodo sono:
o SPWeb spWeb;
o String listName;
o Stream fileStream: è lo stream del contenuto del documento da creare;
o String fileName;
25
o Boolean overwrite: bool per la gestione della sovrascrizione dei file con stesso fileName
nella stessa lista;
o List<String> folderLevelList;
o Boolean appendNewGuid: bool per assegnare un nuovo GUID all’oggetto che si va a
creare;
o Out String url.
In questo caso, dopo aver configurato o meno i permessi elevati per creare il file, viene anche
effettuato l’overload di tale metodo, andando a seguire il flusso nella figura precedente.
Il risultato è quello di salvare l’url relativo del file appena creato all’interno della variabile url,
consegnatoci funzionante dal try / catch di controllo; nel caso di malfunzionamenti, verrà
generata un’eccezione e restituito un url vuoto.
3.3.1.1.4 Void DeleteFile Al contrario del metodo precedente, questo andrà a rimuovere il file indicato. Come parametri
di input avrà difatti, oltre al classico spWeb, l’url del file e il boolean forceElevatePrivileges.
A seconda del forceElevatedPrivileges, il metodo accederà o no in un SPWeb con i privilegi da
amministratore, per poi fare un spWeb.GetFile(url) e rimuovere questo.
3.3.1.1.5 Metodi di controllo A supporto dei metodi descritti in precedenza, abbiamo tre metodi di controllo dei file names
ed uno per il controllo del path di destinazione dei file.
3.3.1.1.5.1 File Name Questi tre metodi servono a ripulire i nomi dei file che verranno caricati a livello
programmatico all’interno di Lists e Document Libraries, in modo tale che queste ultime
possano accettarli senza avere alcuna generazione di errore. Il fatto di non aver errori a livello
di caricamento di file creati è fondamentale per poter evitare documenti rotti o spezzati.
3.3.1.1.5.1.1 Boolean CheckLengthFileName Verifica la lunghezza della stringa in input. Restituisce true se la lunghezza di tale è minore di
una costante definita nella classe.
26
3.3.1.1.5.1.2 Boolean checkFileName Verifica la correttezza del nome del file, controllando l’assenza di caratteri speciali all’interno
della stringa in input. Restituisce true nel caso venga superato il controllo.
3.3.1.1.5.1.3 String CleanFileName Ripulisce il filename dai caratteri non ammessi, nel caso vi fossero, e accorcia la lunghezza del
file ad un valore pari alla costante definita nella classe, in modo tale da essere caricabile
all’interno delle strutture di interesse.
3.3.1.1.5.2 Path Il controllo sul percorso in cui andare a inserire è importante quanto la corretta definizione del
nome del file stesso. Cercare di mettere un documento all’interno di uno spazio non esistente
apporterebbe degli errori non indifferenti, primariamente nella creazione ed inserimento del
documento stesso, poi perché andrebbe ad inficiare sul flusso dei dati di nostro interesse.
Per questo motivo è stato sviluppato il seguente metodo.
3.3.1.1.5.2.1 Void EnsureFolders Questo è il metodo di appoggio più interessante, poiché va a verificare l’esistenza delle folder
del percorso del file che si andrà a creare (spostare), in tal modo da aver effettivamente una
folder in cui porre quest’ultimo.
Il diagramma di flusso del metodo è quello descritto nella pagina successiva.
27
3.3.1.2 Groups La seconda classe che verrà analizzata è quella dei gruppi: all’interno di questa sono stati
implementati tutti quei metodi che portano alla creazione, eliminazione e verifica dei gruppi
all’interno della site Collection di nostro interesse.
3.3.1.2.1 SPGroup Create Il metodo va a creare un nuovo gruppo all’interno della Site Collection, segnalando errore nel
caso, ad esempio, questo già esista. Non è necessario l’accesso con permessi elevati, poiché
tali operazioni si presume possano essere utilizzate unicamente da utenze già abilitate con tali
ruoli.
Gli argomenti di input sono:
o SPWeb spWeb;
Figura 12 - Flusso ensureFolders
28
o String spGroupName: Il nome da assegnare al gruppo;
o String spGroupDescription: la descrizione del gruppo;
o SPMember groupOwner: l’owner del gruppo che si va a creare;
o SPRoleDefinition spRoleDefinition: il ruolo assegnato di default al gruppo all’interno
della Site Collection.
Il flusso del metodo è così descrivibile:
Allo stesso modo, vi è un metodo in overload che invece di prendere il parametro
SPRoleDefinition ha come argomento un SPRoleType: questo richiama il Create con
spRoleDefinition = spWeb.RoleDefintions.GetByType(roleType)
3.3.1.2.2 void CreateIfNotExistsPermissionLevel Il metodo qui descritto va a verificare l’esistenza di un livello di permessi da poter assegnare,
in seguito, ad un determinato gruppo: se questo non esistesse, verrà creato.
Argomenti richiesti sono:
o SPWeb spWeb;
Figura 13 - Flusso SPGroupsCreate
29
o String permissionLevelName: il nome del livello di permessi che si intende verificare;
o String permissionLevelDsc: la descrizione del livello, nel caso se ne creasse uno nuovo;
o SPRoleType: il ruolo associato a questo livello, nel caso se ne creasse un nuovo
Il codice è di per sé particolare: sfruttando il try / catch come se fosse un if, nel caso non
esistesse il tipo di permesso associato al permissionLevelName, all’interno del catch sia andrà
a definire quest’ultimo, con nome, descrizione e ruolo. In caso di funzionamento corretto, non
verrà eseguito alcunchè.
3.3.1.2.3 Void FindGroupToDeleteToCreate Questo metodo accessorio permette di restituire un elenco (nuovo) di gruppi da eliminare e di
popolare un’altra list con quelli da creare, verificando tra quelli già esistenti.
Input del metodo sono:
o SPWeb spWeb;
o SPGroupCollection spGroupCollection: è la collezione di gruppi da controllare;
o Ref List<String> newGroupNameList: l’elenco dei gruppi da aggiungere (è una lista già
preesistente passata dal processo invocante) [è fondamentale che questo elenco sia
ordinato alfabeticamente];
o Out List<String> spGroupListToDelete: è l’elenco dei gruppi da rimuovere;
Il metodo controlla di non aver già analizzato per intero i contenuti della collection di gruppi
spGroupCollection e la lista dei nomi newGroupListName.
Se così fosse, entra in un secondo ciclo while che confronta i nomi dei gruppi presenti. Il
compare dei nomi serve proprio a questo: nel caso il gruppo seguisse nell’ordine un gruppo già
presente, visto l’ordinamento alfabetico di entrambe le liste, andrebbe ad implicare l’inutilità
del gruppo sopra citato, e dunque avente diritto ad entrare immediatamente nelle liste da
cancellare.
Nel caso invece i due nomi coincidessero (dunque il compare tra newGroup e spGroup
risultasse pari a 0), il newGroup non sarebbe da aggiungere, e dunque andrebbe rimosso
dall’elenco dei nomi “nuovi”.
30
Ad ogni passaggio viene verificato che la collection spGroupCollection abbia un valore
maggiore a quello del suo counter (sennò finirebbe immediatamente il processo in atto);
superati i while, dunque, avremmo le liste popolate in maniera da avere i gruppi non esistenti
da una parte, quelli da rimuovere dall’altra. A completare il ciclo, vengono verificati gli ultimi
Gruppi che non siano stati confrontati: questi stessi verrebbero spostati nella lista dei gruppi
da rimuovere, e mandato dunque, alla fine del for, il processo in chiusura. Il diagramma di
flusso è:
Figura 14 - Flusso FindGroupToDeleteToCreate
31
Come sottolineato, l’ordinamento alfabetico è trascendentale per il corretto funzionamento
del metodo: se andassimo ad operare su di un elenco non ordinato, il metodo di controllo si
sfalderebbe al primo gruppo non ordinato, e dunque andremmo a rimuovere gruppi da
mantenere oppure ad aggiungere gruppi già esistenti, andando incontro ad un’inevitabile
crash.
3.3.1.2.4 Boolean hasCurrentUserAPermissionLevel Il metodo in questione verifica se un determinato utente ha almeno un livello di permessi
all’interno della site Collection presa in considerazione, e torna true nei casi in cui soddisfi
questa richiesta, oppure sia siteAdmin.
Questo metodo poggia su di un altro presente in questa classe, il
isPermissionLevelInRoleAssignment (che verrà descritto in seguito), ed ha come parametri di
input il classico spWeb e l’elenco di string permissionLevelsName di cui verificare la presenza.
In questo caso, per poter verificare i permessi, necessitiamo di un accesso con privilegi Elevati.
Il metodo si comporta in questo modo:
1. Viene settato a false il valore da mandare come output del modulo;
2. Viene creata una chiave per tutti i gruppi che contengono lo user preso in
considerazione, e la metto all’interno del dictionary groupUserHasAccess;
3. Viene creato l’ambiente per operare con i privilegi elevati;
4. Si verifica se è admin della site Collection: se si, ritorna true;
5. Se non passa la verifica, viene generata una spGroupCollection dei gruppi presenti sulla
site Collection, ed un SPRoleAssigmentCollection dei permessi presenti sulla stessa;
6. Per ogni gruppo della spGroupCollection viene lanciata una query linq in cui si verifica
se vi è un record che appartenga alla dictionary e che abbia lo stesso Group.ID;
7. Se sì, si verifica il gruppo abbia uno dei livelli permessi elencati all’interno del
permissionLevelsName: in caso affermativo, setto il valore di output a true e faccio un
return di quest’ultimo;
8. Nel caso non risultasse alcun permesso associato ai gruppi, vi sarebbe un’ulteriore
verifica, tramite il metodo isPermissionLevelInRoleAssignment, rispetto al singolo
32
utente: con lo stesso ragionamento proposto al punto 7, se verrà riscontrato almeno
uno dei permessi richiesti, verrà ritornato true;
9. Nel caso si giungesse a questo punto, il metodo ritornerà false.
Il tutto permetterà di ovviare a dover passare per via di interfaccia alla scansione dei permessi
di un utente all’interno di una site Collection.
Allo stesso modo, è stato implementato un ulteriore metodo in overload che, oltre a restituire
il booleano, rende in out l’elenco dei gruppi in cui lo user ha i permessi ricercati.
3.3.1.2.5 Boolean isPermissionLevelInRoleAssignment Quest’ultimo metodo della classe ci permette di verificare se un RoleAssignment contiene uno
dei RoleDefinitionBindings presenti all’interno della lista di permessi passata in input. Presi
come argomenti:
o SPRoleAssigment spRoleAssigment: è il ruolo da verificare
o String[] permissionLevelsName: è il nome dei permessi da verificare
Verranno estratti i livelli di permesso associati all’spRoleAssigment, e per ognuno di questi
attuato un compare del loro nome con le stringhe: in caso affermativo, il metodo restituirà
true.
33
3.3.1.3 KeyValList La terza classe in oggetto è quella che consente una generazione rapida di liste di
Configurazione da associare alla site Collection, generando, di principio, una lista strutturata
come un dictionary con key e value.
I metodi di questa classe risultano fortemente correlati tra loro: dunque, per agevolare la
comprensione di questi, non verrà seguito un ordinamento alfabetico, ma piuttosto verrà
seguito, dal basso verso l’alto, l’ordine di incapsulamento di questi, descrivendo quelli che poi
verranno richiamati all’interno degli altri.
3.3.1.3.1 Bool TryAddKey Il metodo in oggetto va ad aggiungere un nuovo item nella lista di nome listName con chiave
key e valore value. I parametri di ingresso sono:
o SPWeb spWeb;
o String listName;
o String key;
o String value;
Il metodo esegue una query linq all’interno della lista, e verifica che non vi sia già un item con
key identica a quella passata. In conclusione, il flusso sarà il seguente:
Figura 15 - Flusso TryAddKey
34
3.3.1.3.2 void CreateKeyValueListNoPrivileges Questo metodo permette la generazione effettiva della Lista di Configurazione all’interno della
propria site Collection, con la generazione della stessa in caso di necessità, e di popolamento
tramite il dictionary passato.
Argomenti del metodo sono:
o SPWeb web;
o String listName;
o Dictionary<String,String> keys: è l’elenco di chiavi da inserire all’interno della lista;
o KeyValueListPermissions permissions: è il tipo di permessi da assegnare alla lista
Quest’ultimo type è generato appositamente per la classe in questione, permettendo la
gestione dei permessi in modalità ereditata dall’ambiente oppure Admin only.
La funzione verifica se la lista di configurazione non sia già esistente, tramite l’utilizzo
particolare del try/catch, e dunque va ad inserire, nella lista esistente (o creata dal metodo
stesso) il dictionary passato in input, controllandone l’univocità dei parametri passati.
Questo va ad esplicitare il funzionamento del try / catch: nel caso di non esistenza della lista, la
funzione andrebbe in errore, ma il catch, come da corretto funzionamento, cattura questo
scatenando la creazione della lista stessa ed andando a popolarlo di conseguenza.
La pulizia dei permessi tramite il tipo KeyValueListPermissions permette inoltre di tutelare i
contenuti della lista stessa da modifiche indesiderate da parte di utenze in teoria non abilitate.
Il diagramma di flusso è dunque il seguente:
35
Figura 16 - Flusso CreateKeyValueListNoPrivileges
3.3.1.3.3 Void CreateKeyValueList Questo è il metodo che va a richiamare il precedente per poter funzionare. Ricevendo come
input:
o SPWeb web;
SPList spList = web.Lists[listName]
try
Visitata tutta la dictionary
Log dell’add riuscito
TryAddKey
Generazione della Lista di Configurazione noCrawl = true
spDefaultView.ViewFields.Add(VALUE_FIELD_NAME)
try
Visitata tutta la dictionary
Add dell’item
Permissions = ONLY_SCA
Rimuovi tutti I permessi sulla lista
Log di errore di creazione
VERO
VERO
FALSO
FALSO
CATCH E
CATCH E
FALSO
FALSO
VERO
VERO
36
o String listName;
o Dictionary<String,String> keys;
o KeyValueListPermissions permissions;
o Boolean forceToElevatePrivileges
Questo prepara, a seconda del valore di forceToElevatePrivileges, l’ambiente in cui invocare il
CreateKeyValueListNoPrivileges, passando come parametri quegli stessi ricevuti come
argomenti alla rispettiva invocazione, senza operarne alcuna modifica.
3.3.1.3.4 String GetValueFromKeyNoPrivileges Seguendo la strutturazione dei metodi precedenti, questo va ad essere il “nucleo operativo”
dell’operazione di ricerca della key e di restituzione del rispettivo value.
Ricevendo come argomenti:
o SPWeb web;
o String listName;
o String key: è il parametro della chiave da ricercare;
o Out SPListItem item: è l’item su cui salvare la ricerca.
Questo pesca la key in questione all’interno della lista definita con listName, passa l’item
ritrovato in out e restituisce il value dell’item stesso.
3.3.1.3.5 String GetValueFromKey Come il metodo CreateKeyValueList, quest’ultimo prepara l’ambiente per invocare il
GetValueFromKeyNoPrivileges, a seconda del bool che riceve in argomento:
o SPWeb web;
o String listName;
o String key;
o Out SPListItem item;
o Boolean forceToElevatePrivileges.
Allo stesso modo esiste un metodo overload senza l’argomento out SPListItem: in questo caso
ne viene generato uno in locale e passato come argomento per invocare il metodo
GetValueFromKeyNoPrivileges.
37
3.3.1.3.6 Void SetOrAddValueNoPrivileges Ricevendo come parametri di ingresso:
o SPWeb web;
o String listName;
o String key;
o String value
Questo verifica (tramite query linq) se è già presente un item con quella key, ne crea uno se
non esistente, e dunque setta il valore del campo VALUE con quello passato in ingresso.
3.3.1.3.7 Void SetOrAddValue Come per i metodi precedenti, anch’esso genera l’ambiente con o senza privilegi elevati per
eseguire il SetOrAddValueNoPrivileges.
3.3.1.4 Lists Questa quarta classe ha un comportamento e dei metodi similari a quelli proposti all’interno
della DocLib class, poiché invece di operare su di una Document Library, operiamo su di una
Lista, che, dal punto di vista di SharePoint, risultano essere delle strutture similari tra loro.
Prima di iniziare a descrivere i metodi, è da analizzare la classe introdotta al suo interno, per il
tipo Field, utile per la gestione del tipo di campo da inserire in una lista.
3.3.1.4.1 Class Field
Questo type è costituito da 4 properties e due costruttori, così definiti:
SPFieldType Type: definisce il tipo di campo da inserire nella lista;
Bool Required: impostazione dell’obbligatorietà sul campo;
Bool AllowMultipleValues: configurazione della possibilità di più valori per il campo in
questione;
String[] Choice: i possibili valori associabili al campo stesso
I costruttori invece si differenziano nella gestione dei campi AllowMultipleValue e Choice:
1. Il primo costruttore definisce le possibili choices all’interno dell’oggetto
2. Il secondo definisce se è possibile un valore multiplo per lo stesso
38
3.3.1.4.2 SPListItem CopyItemTo Questo metodo permette la copia di un item da una lista ad un’altra che abbia almeno i campi
di questo già definiti al suo interno. Come argomenti abbiamo:
o SPListItem item: è l’item da copiare;
o SPList destinazione: è la lista di destinazione;
o SPFolder allegati: è la cartella che comprende gli allegati da copiare
Il metodo opera in questo modo:
1. Viene creato un nuovo item nella lista di destinazione
2. Per ogni field all’interno dell’item, viene verificato che non sia un readOnlyValue, non
sia un campo calcolato e non sia uno dei campi built-in delle liste di SharePoint, e
verifica che un campo con quel nome esista effettivamente
3. Se supera il test al punto sopra, inserisce il valore all’interno del campo di pertinenza, e
ripete 2. finchè non ha verificato tutti i campi dell’item;
4. Per ogni attachment passato, ne recupera l’oggetto fisico (tramite l’url dell’item di
origine);
5. Ne apre un array di byte;
6. Lo allega all’item nuovo, e ripete da 4 per tutti gli attachments;
7. Rimuove tutti i permessi del nuovo item;
8. Prelevando i ruoli dall’item di origine, li trasferisce al nuovo;
9. Per tutti gli allegati dell’SPFolder li trasferisce associandoli all’item stesso;
10. Restituisce il nuovo item.
3.3.1.4.3 SPListItem MoveItemTo Il metodo opera in maniera similare al precedente. Unica differenza è l’eliminazione dell’item
di origine alla fine della funzione.
3.3.1.4.4 SPList Create Consente la generazione, in modalità diverse, delle liste. È un metodo in overload, con 4
signature diverse. Argomenti in comune sono:
o SPWeb web;
o String name: il nome della lista da creare
39
Mentre a differire è il modo in cui vengono passati i tipi di campo all’interno della lista stessa:
1. Dictionary<String,Fields> fields
Dopo aver creato una nuova lista generica con il nome passato in input, viene analizzato il
dictionary in tale modo:
È importante notare che i campi SPFieldChoice e SPFieldUser debbano avere un percorso
stante a se stesso poiché sono gli unici che richiedono dei parametri particolari (le possibili
choices in un caso, l’AllowMultipleUser nell’altro) da inserire. Gli altri necessitano unicamente,
nel nostro interesse, del solo nome di campo, il tipo dello stesso ed il boolean per la
configurazione dello stato required.
2. List<SPFields> fields
In questo caso i campi sono già strutturati, perché la lista riceve dei tipi di campo. Dunque la
funzione si riduce ad aggiungere alla vista il campo e configurarne il suo tooltip, definendone
la possibilità di visualizzazione in tutte le possibili form della lista stessa.
Tutte le complicazioni illustrate in 1. non vi sono poiché i campi non devono essere creati ex-
novo.
Fields[nomeCampo].type SPFieldChoice scelta
Choice != null
Aggiungi scelte possibili
SPFieldUser user
MultiUser == true
Consenti MultiUser
Aggiungi alla lista
Aggiungi alla lista con i parametri necessari
Aggiungi il campo alla vista di default
Tipo SPFieldChoice Tipo SPFieldUser
Altri Tipi
VERO VERO
FALSO
Figura 17 - Flusso Create
40
3. String contentTypeId, SPListTemplateType listType
Con questa signature l’idea è quella di permettere la generazione di una lista con template di
base definito dall’utente e settarne il relativo content type tra quelli disponibili. Il content type
permette di definire il metedata ed il behaviour per un determinato data entity, a cui sono
associati i relativi workflow, policy, site columns.3
Il metodo opera in tale maniera:
i. Viene generata la lista;
ii. Per la lista viene abilitata l’associazione dei content types (list.ContentTypesEnabled);
iii. Viene creata un elenco toDelete dei content types da rimuovere recuperando tutti
quelli già associati alla lista stessa;
iv. Viene generato un nuovo Content type definito tramite la stringa contentTypeId;
v. Vengono rimossi tutti i content types dell’elenco toDelete associati alla lista in
questione
Come oggetto in uscita abbiamo la lista stessa creata
4. String contentTypeId
Quest’ultimo si rifà al metodo descritto in 3., con l’unica eccezione che il il template della lista
è predefinito in SPTemplateListType.GenericList.
3 http://msdn.microsoft.com/en-us/library/ff798404.aspx come riferimento e descrizione riguardo il Content type di
una lista o document Library
41
3.3.1.5 Mailer La classe mailer è tra le più importanti, se non la più importante tra quelle sviluppate.
Il metodo di gestione della mail in SharePoint funziona in maniera similare ai classici event
handler esistenti: può essere integrata la sua gestione all’interno di un workflow o ad un
qualsiasi evento di alert, ma non a degli eventi custom operativi a prescindere.
Questo è lo scopo del mailer proposto: fornire dei metodi che garantiscano,
indipendentemente dalla struttura a workflow o da eventi scatenati dal sistema stesso, la
gestione della mail, i relativi contenuti, i mittenti ed i destinatari in modo più autonomo e
libero possibile.
Essendo poi la società orientata a non sfruttare la struttura di workflow proposta, è
fondamentale una gestione esterna di tali processi, in modo tale da poter usuffruire
ugualmente di un servizio che risulta sempre più importante nella pianificazione, sviluppo e
gestione di un ciclo produttivo industriale in maniera completa ed efficiente.
Dunque, la classe fornirà primariamente 4 diversi metodi, ed un costruttore di classe per
definire il tipo EmailTemplate, che descriverà subject e body della mail stessa.
È inoltre interessante notare che, a differenza di tutte le altre classi, gli import da package
esterni è molto più vasto, specie per poter consentire l’uso di server SMTP per l’invio delle
mail stesse.
Gli import eseguiti sono:
o System.Net4: permette di avere metodi di gestione dei protocolli di comunicazione su
reti
o System.Net.Mail5: è il namespace che permette la gestione dell’invio dei messaggi
tramite il server SMTP;
o System.Collections.Specialized6: namespace che permette una gestione di raccolte
particolarmente specializzate o tipizzate
4 http://msdn.microsoft.com/it-it/library/system.net.aspx
5 http://msdn.microsoft.com/it-it/library/system.net.mail.aspx ne descrive metodi e funzioni
6 http://msdn.microsoft.com/it-it/library/system.collections.specialized.aspx
42
o Microsoft.Sharepoint.Administration7: namespace che permette una più vasta gestione
dei tipi e membri da configurare durante il deploy;
o Microsoft.Sharepoint.Utilities8: comprende un insieme di metodi per una più pratica
gestione della piattaforma SharePoint;
o System.Web.UI.WebControls9: consente la creazione di controlli server all’interno di
una pagina web, risultando necessario nel caso di utilizzo del metodo all’interno di
ulteriori event handler.
3.3.1.5.1 Class EmailTemplate È strutturata in maniera molto semplice:
o Una stringa pubblica di Subject;
o Una stringa pubblica di Body;
o Un costruttore di classe che setta i due valori definiti in precedenza
3.3.1.5.2 Void createEmailTemplateList Questo metodo è utile a preparare l’ambiente per la gestione delle mail all’interno della site
collection, definendo la lista di appoggio in cui vanno inserite i template delle mail da inviare,
con i relativi placeholder da rimpiazzare nel momento di personalizzazione della stessa.
Il metodo ha come argomenti queste variabili:
o SPWeb web;
o Dictionary<String, EmailTemplate> emailTemplates: è l’insieme dei templates passati
per la generazione della lista di configurazione;
o KeyValueList.KeyValueListPermissions permissions: sono i permessi per la generazione
della lista di configurazione;
o Boolean forceToElevatedPrivileges
Ed esegue questa funzione:
1. Viene creato un nuovo Dictionary<String, String> denominato keys;
2. Per ogni key dell’emailTemplates, vengono generate due key all’interno di keys con tale
struttura:
7 http://msdn.microsoft.com/it-it/library/microsoft.sharepoint.administration.aspx
8 http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.utilities.aspx
9 http://msdn.microsoft.com/it-it/library/system.web.ui.webcontrols.aspx
43
Key Value
Key + “body” emailTemplates[key].body
Key + “Subject” emailTemplates[key].subject
3. Viene invocato il metodo KeyValueList.CreateKeyValueList(web,
EMAIL_TEMPLATE_LIST, keys, permissions, forceToElevatedPrivileges), per ottenere la
lista di nostro interesse.
La necessità di spezzare in due keys si basa sul fatto di poter usufruire dei metodi generati in
precedenza, cosicché non si debba creare ulteriore codice già fornito da funzioni similari già
scritte.
3.3.1.5.3 Void getEmail Questo è il metodo che va a pescare dalla lista generata in precedenza fornendo body e
subject della mail da inviare, e sostituendo i placeholder con i valori reali da introdurre.
Gli argomenti in ingresso sono:
o SPWeb web;
o String emailType: definisce il tipo di emailTemplate da pescare;
o Dictionary<String, String> replaceTable: è la lista con cui vengono sostituiti i
placeholder con i valori reali;
o Out String body: è il valore del body che viene restituito in uscita;
o Out String subject: è il valore del subject restituito in uscita
È importante sottolineare un fatto: il replaceTable è un dictionary che, pur avendo una
struttura implementabile a livello generico, si è scelto di consentire allo sviluppatore di averne
piena libertà di creazione, lasciando questa senza un metodo di composizione appropriato.
Poiché ogni implementazione del servizio mail è costumizzato in maniera specifica al progetto
di interesse, vincolare la raccolta dei dati renderebbe praticamente bloccata la struttura di
tutta la site collection, bloccando liste, dati, contenuti e particolarità che il cliente potrebbe
andare a richiedere per la propria applicazione.
Da un’analisi teorica, il dictionary andrebbe ricreato ogni volta, poiché sono sin troppe le
variabili in gioco che potrebbero cambiare (numero di placeholder, ente invocante, ente
44
ricevente, variabili da inserire nei placeholder, per citarne alcuni), che non permettono di
avere un oggetto (item di una lista) fisso da sfruttare.
Nel caso di una lista, ipotizzando di avere n campi con m possibili valori teorici per ognuno di
essi, avremmo un ordine di grandezza di nm, generando una mole di dati ingestibile
all’aumentare di n ed m, oltretutto portando ad un vantaggio in termini di tempo a dir poco
irrisorio: l’accesso alle liste è praticamente immediato, ed allo stesso modo recuperare i valori
all’interno degli items selezionati. Una minima perdita in termini di tempo sopperisce appieno
al risparmio in termini di spazio occupato che proporrebbe l’altro tipo di soluzione.
Tornando a parlare del metodo, esso esegue queste operazioni:
i. Nelle variabili body e subject in ingresso vengono posti dei valori di esempio;
ii. Vengono recuperati, tramite il metodo della classe KeyValueList GetKeyValue i
contenuti di body e subject di interesse per la mail;
iii. Per ogni keyValuePair presente nel dictionary, viene verificata la possibile sostituzione
del placeholder: se il value non è null, viene presa la sezione del placeholder
(caratterizzata da “%”+ entry.key + “%”) e sostituita sia nel body che nel subject dal
value effettivo, oppure, nel caso contrario, con uno spazio vuoto;
Tutto il processo è interno ad un try / catch, che in caso di errore generico manda una
segnalazione nel log di sistema.
3.3.1.5.4 Void Send Questo metodo consente l’effettiva generazione della mail e il conseguente invio della stessa
tramite il metodo fornito dalle SPUtility SendEmail, senza avere degli allegati ad essa associata
(per gli allegati, si rimanda al metodo successivo).
Come signature, il metodo ha:
o SPWeb web;
o String to: è l’indirizzo mail del destinatario;
o String tipoMail: è il tipo di mail template da recupare;
o Dictionary<String, String> replaceTable;
o String from: è l’indirizzo mail del mittente;
o String emailCC: sono gli indirizzo mail degli utenti a cui la mail viene inoltrata in copia.
45
Il flusso è così descritto:
Figura 18 - Flusso Send
Come è possibile constatare, il metodo verifica la presenza dei campi nulli per i ruoli cardine
dell’invio della mail (mittente), generando un’exception nel caso di valori mancanti.
A completare, associato a questo stesso metodo ve ne è un altro in overload, con signature
leggermente diversa:
o Invece di avere una variabile to di tipo string, ne abbiamo una identica di tipo SPUser
String messaggio;
String oggetto
getEmail(web, tipoMail, replaceTable, out oggetto, out messaggio)
stringDictionary headers = new StringDictionary() headers.Add(“to”, to);
From != null Errore
Headers.Add(“from”, from)
emailCC != null
Headers.Add(“cc”, emailCC)
FALSO
FALSO
VERO
VERO
Headers.Add(“subject”, soggetto) Headers.Add(“content-type”, “text/html”)
SPUtility.SendEmail(web, headers, messaggio)
46
FALSO
Urls != null
Foreach(url)
Tr
y
SPFile file = web.GetFile(url)
Message.Attachments.Add(new
Attachment(file.OpenBinaryStream(), file.Name)
Errore
VERO
FALSO
VERO
EXCEPTION E
Questo dunque andrà a recuperare la mail associata allo User passato e, se questa risulterà
esistere, verrà inviata la mail invocando il metodo descritto sopra.
3.3.1.5.5 Void SendWithAttachments Quest’ultimo metodo della classe è decisamente più articolato dei precedenti, poiché
l’implementazione dell’inserimento degli allegati richiede numerosi passaggi supplementari.
Oltre agli argomenti descritti nel metodo Send, quest’ultimo ha una variabile supplementare:
o String[] urls: il percorso dei file da allegare
Il metodo, dopo aver definito le string messaggio e oggetto, crea un nuovo oggetto di tipo
MailMessage, a cui vengono associati, se presenti, mittenti, destinatari e lettori in copia (con le
stesse restrizioni presenti in Send).
Dopo aver associato alle properties dell’oggetto MailMessagge i valori
Property Value
isBodyHtml True
Body messaggio
Subject oggetto
Viene verificata la presenza di elementi nell’array urls
Figura 19 - Flusso SendWithAttachments
47
In modo tale da consentire l’associazione al messaggio di tutti gli allegati effettivamente
esistenti, senza generare problemi verso quelli funzionanti ed associabili.
A questo punto, poiché non è possibile utilizzare il metodo SPUtility.SendEmail proposto in
Send, dato che questo non gestisce propriamente gli allegati, c’è il bisogno di ricreare
l’ambiente smtp per l’invio della mail:
o Viene recuperato il Local.OutboundMailServiceInstance, che è l’istanza locale che
definisce i settaggi per l’invio delle mail tramite smtp;
o Se non esistente il serviceInstance descritto al punto precedente, viene settato come
suo valore il web.Site.WebApplication.OutboundMailServiceInstance, così da avere
quello stesso della site collection; in caso di assenza pure di questo si da errore e viene
impedito l’invio;
o A questo punto viene recuperato l’smtp server address tramite il
serviceInstance.Server.Address, e generato un nuovo smtp client puntato a questo
indirizzo;
o Ora non resta che inviare il message tramite il comando client.Send(message)
La necessità del controllo sul Local.OutboundMailServiceInstance è per ovviare al valore null
che questo assume arbitrariamente, impedendo l’invio stesso della mail al metodo. Con il
web.Site.WebApplication.OutboundMailServiceInstance i rischi di null exception si riducono al
minimo, garantendo dunque il corretto funzionamento dell’smtp client.
48
3.3.1.6 PubManager La classe PubManager fornisce quei metodi che permettono la configurazione delle
PublishingWeb10 e PublishingPage11 classes.
PublishingWeb, come descritto nelle specifiche Microsoft, “provides publishing-specific
behavior for an SPWeb that supports publishing, including access to child PublishingPage and
PublishingWeb instances, variations support, navigation settings, PageLayout and Web
template restrictions, and Welcome page settings. This class wraps an SPWeb instance that
has the publishing feature activated”. In questo modo, nelle site collection in cui vi è
implementata la feature di publishing al suo interno, viene permessa la definizione custom di
tutte quelle pagine su cui potranno intervenire gli utenti finali tramite il front-end della site
collection, configurando primariamente i permessi su PageLayout e sul Web Template, e
gestendo gli accessi sulle Pagine di Publishing e sui Web di Publishing figlie di questa.
PublishingPage invece, sempre dalla specifiche Microsoft, “contains references to the parts
that define the .aspx page, such as the PageLayout class, the SPContentType class, resources,
and other parts. It contains PublishingPage content as field values in the document library
item”. In questo modo le possibili pagine di Publishing, oltre che ad ereditare dal
PublishingWeb, può aver definite le proprie caratteristiche particolari usando le strutture base
di SharePoint (in questo caso, Document Library) e venendo trattata come un qualsiasi altro
item, e dunque con le stesse personalizzazioni.
Anche in questo caso vi è la necessità di creare un oggetto che definisca un insieme di variabili,
che verrà definito PageDefinition. Invece di creare una classe pubblica, si è optati di usare uno
struct, visto che non abbiamo metodi costruttori ma unicamente variabili al suo interno. I
metodi ritenuti utili alla causa invece sono sette, con, in alcuni casi, overload di questi.
3.3.1.6.1 Struct PageDefinition
Lo struct ha 7 variabili private al suo interno, a cui vi si ha accesso tramite i metodi get / set ad
esse associati:
String pageFileName: è l’url della PublishingPage da generare;
String pageTitle: è il titolo della PublishingPage;
10
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.publishing.publishingweb.aspx 11
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.publishing.publishingpage.aspx
49
String controlPath: è l’url, se definito, dello user control associato alla pagina;
String pageLayout: è il nome della PageLayout associata alla PublishingPage;
Boolean includeInCurrentNavigation: indica se inserire o no nel site (o subsite) di
pertinenza il suo link diretto;
Boolean includeInGlobalNavigation: indica se inserire o no nella site collection di
pertinenza il suo link diretto;
String webPartZoneId: legato al controlPath, definisce in quale WebPartZone inserire lo
user control definito in precedenza.
3.3.1.6.2 PublishingPage CreatePublishingPage Il primo metodo implementato è quello che operativamente crea la PublishingPage e lo
inserisce all’interno della PublishingPageCollection passato in ref.
Come argomenti abbiamo:
o SPWeb web;
o String pageNameUrl: è l’url della pagina da generare;
o String pageTitle: è il titolo della pagina;
o String pageLayoutName: è il nome del PageLayout da associare;
o Ref PublishingWeb pubWeb: è la PublishingWeb da cui pescare, in caso di evenienza, la
PublishingPageCollection;
o Ref PublishingPageCollection pubPages: è l’insieme delle pagine a cui verrà aggiunta
quella in fase di creazione.
Il funzionamento è il seguente:
i. Se pubWeb è vuoto, vengono associate ad esso le PublishingWeb di web tramite il
metodo PublishingWeb.GetPublishingWeb(web);
ii. Se pubPages è vuota, viene associata la collection di PublishingPages di pubWeb
tramite il metodo pubWeb.GetPublishingPages();
iii. Viene creato un oggetto PageLayout recuperando dal web quello definito con il name
pageLayoutName con il metodo GetPageLayout(web, pageLayoutName) (che verrà
descritto a breve);
50
iv. Viene creato un riferimento PublishingPage chiamato pubPage a cui viene associato
l’oggetto che viene creato all’interno di pubPages con il metodo
pubPages.Add(pageNameUrl, pageLayout);
v. Viene valorizzata la property Title di pubPage con il valore pageTitle, ed eseguito un
update dell’oggetto stesso.
Il valore restituito sarà la stessa PublishingPage generata.
In caso di eccezioni, verrà generato un messaggio di Log con i riferimenti a ciò che a portato
questo errore.
Il metodo, oltretutto, effettua un overload in cui la signature manca degli argomenti webPub e
webPages: il metodo setterà questi a null e invocherà il metodo appena descritto.
3.3.1.6.3 PageLayout GetPageLayout Questo metodo accessorio è utile nel CreatePublishingPage per recuperare il PageLayout
associato alla stringa passata. Gli argomenti del metodo sono:
o SPWeb web;
o String pageLayoutName;
Il metodo recupera il PublishingSite della site Collection, e l’associata PageLayoutCollection, va
a prendere il relativeUrl in questione.
Se la stringa ottenuta risulta uguale al solo “/”, stando ad indicare che ci si trova di fronte ad
una site collection posta come primaria all’interno della Web Application, andremo ad
attingere direttamente da “/_Catalogs/masterpages/<PageLayoutName>”; viceversa, nel caso
ci trovassimo in una site collection più interna, avremmo come indirizzo di riferimento
“<web.Site.RelativeUrl>/_catalogs/masterpages/<PageLayoutName>”.
3.3.1.6.4 List<PageDefinition> CreatePageDefinitionList Questo metodo di appoggio permette di creare, come definito dalla signature, la lista delle
PageDefinition da dare in pasto alle altre funzioni prendendo i dati dalla matrice passata in
input.
Unica variabile di input è la matrice di String[,] pageDefinitionMatrix, che conterrà i valori, in
ordine:
51
PageFileName;
PageTitle;
ControlPath;
PageLayout;
WebZonePartId;
IncludeInCurrentNavigation;
IncludeInGlobalNavigation;
Per poter popolare l’oggetto PageDefinition in creazione.
Il metodo analizzerà tale matrice, e per ogni riga, fino al raggiungimento dell’UpperBound,
verrà generato un oggetto PageDefinition con i valori relativi, ed inserito all’interno di una
lista, che sarà oltretutto l’output della funzione stessa.
3.3.1.6.5 List<PublishingPage> CreatePublishingPagesSetWelcome Questo metodo porta alla generazione della Lista delle publishing Pages. Come argomenti
della signature abbiamo:
o SPWeb web;
o List<PageDefinition> pageDefinitions: è la lista con le PageDefinition da convertire in
publishing Pages;
o String welcomePageFileName: è il nome della pagina che diventerà quella di Welcome.
La costruzione della lista di PublishingPages avviene sin dall’inizio, e viene seguita dalla
configurazione della SPFile welcomePage, della PublishingWeb pubWeb e della
PublishingPageCollection pubPages a null.
Dunque, per ogni PageDefinition all’interno della lista, viene avviato un try / catch strutturato
che permetterà di poter creare tutte le Publishing pages effettivamente funzionanti, senza
dare un blocco nel caso di malfunzionamento di una di queste.
Completato, si passa alla fase di associazione della welcomePage: nel caso il valore della
stringa risultasse non nulla:
i. Si rompe la navigazione sia per la CurrentIncludesPages che per la GlobalIncludePages;
ii. Viene settata la pagina definita come pubWeb.DefaultPage;
52
iii. Viene eseguito un update del pubWeb;
iv. Viene chiuso pubWeb
Da evidenziare, oltretutto, che il metodo stesso ha un caso di overload così definito:
o Invece della List<PageDefinition>, viene passata una matrice pageDefinitionMatrix: verrà
invocato nuovamente il metodo, con List<PageDefinition> ricavata tramite il metodo
CreatePageDefinitionList(pageDefinitionMatrix).
Figura 20 - Flusso CreatePublishingPagesSetWelcome
VERO
FALSO
VERO
FALSO
Try
publishingPage pubPage = PubManager.CreatePublishingPage(…)
pubPage.IncludeInCurrentNavigation
pubPage.IncludeInGlobalNavigation
pageFileName ==
welcomePageFileName
welcomePage = pubPage.ListItem.File
pubPage.checkOut()
pageDefinition.ControlPath !=
null
Inserimento WebPart
pubPage.checkIn()
pubPage.ListItem.File.Approve(String.Empty)
pubPage.ListItem.File.Publish(String.Empty)
pages.Add(pubPage)
Log Error EXCEPTION E
53
3.3.1.6.6 List<PublishingPage> CreatePublishingPages Il metodo proposto è una semplice modifica del metodo descritto al punto precedente: oltre la
matrice ed all’SPWeb, non verrà passato altra variabile. Il return invocherà il metodo
CreatePublishingPagesSetWelcome(web, CreatePageDefinitionList(pageDefinitionMatrix),
String.Empty).
In tale modo non verrà configurata la pagina di Welcome, e verranno conservate le definizioni
di pubWeb.CurrentIncludePages e pubWeb.GlobalIncludePages.
3.3.1.6.7 Void DeletePublishingPagesSetWelcome Al contrario dei precedenti, questo metodo va a rimuovere le Publishing Pages presenti
all’interno della lista di PageDefinition in input, e va nuovamente a configurare la Welcome
Page.
I parametri di input sono similari ai precedenti metodi:
o SPWeb web;
o List<PageDefinition> pageDefinitions;
o String welcomePageFileName.
In questa circostanza, viene:
i. Recuperato il pubWeb da web;
ii. Recuperato il pubPages da pubWeb;
iii. Creato il percorso per associare la nuova WelcomePage, nel caso in cui
welcomePageFileName non fosse nulla;
iv. Per ogni pegeDefinition in pageDefinitions, viene rimosso l’item presente in pubPages
associato al pageFileName tramite un try / catch;
v. Chiuso il pubWeb.
Da notare il “barbaro” utilizzo del try / catch al punto iv. Il catch vuoto, contrario ad ogni tipo
di programmazione pulita e funzionale, è dovuto al fatto che SharePoint, nella versione 2007,
non ha avuto un metodo che eseguisse il tentativo di ricerca dell’oggetto, senza andare in
errore se questo non fosse esistente. In tal maniera, oltre ad avere un controllo sull’effettiva
54
esistenza dell’oggetto, permettiamo anche una retrocompatibilità del metodo con la versione
2007 della piattaforma.
A chiudere la trattazione su questo metodo, è bene far notare, in maniera similare al caso di
CreatePublishingPagesSetWelcome, esiste un metodo in overload per questo stesso, con
variabili di ingresso variate (invece che List<PageDefinition> la matrice pageDefinitionMatrix),
ma stesso comportamento, con return invocante il metodo.
3.3.1.6.8 Void DeletePublishingPages In maniera similare al CreatePublishingPages, riceve come input la matrice
PageDefinitionMatrix, setta come String.Empty la WelcomePage e richiama il metodo
DeletePublishinPagesSetWelcome con argomenti web, pageDefinitionMatrix, String.Empty.
55
3.3.2 Classi accessorie
All’interno della feature descritta, sono state anche introdotte delle classi di supporto che si
sono rese necessarie per un corretto e completo funzionamento di quelle descritte
precedentemente.
Due sono i blocchi cruciali da analizzare: i metodi forniti per il logging e quelli per la gestione
delle security di SharePoint.
3.3.2.1.1 Logging La sezione di logging riveste un ruolo molto importante, in modo particolare nelle situazione di
errore del prodotto: quest’ultima ci permette difatti di verificare, tramite un report puntuale,
cos’è che ha causato l’eccezione.
Potrebbe sembrare una funzione poco funzionale alle specifiche proposte, ma è utile, se non
fondamentale, per lo sviluppatore in caso di problemi riscontrati durante il funzionamento
della solution.
È importante sottolineare, se non troppo evidenziato prima, che praticamente ogni metodo di
quelli descritti nelle classi in precedenza usufruiscono di quelli descritti in questa sezione,
proprio per i motivi citati sopra.
Questa parte di feature è stata spezzata in due classi: quella di Logger, con la creazione della
lista di log, i relativi costruttori e i metodi associati, e la LogExceptions, con i metodi che
invocano i precedenti per una commistione corretta a seconda degli stati in cui ci si trova.
L’elenco di metodi e classi, ora, sarà unificato, elencando prima quelli di Logger.cs, dunque
quelli di LogExceptions.cs.
3.3.2.1.1.1 Class Logger La classe ha 4 variabili private:
SPWeb web;
SPListItem spFeatureLogItem;
SPFile spLogFile;
String logName.
56
Sono tutte a null in origine, e poi verranno popolati, a seconda del caso, tramite i costruttori di
classe:
1. Logger (SPWeb destinationWeb, string feature)
In questa prima situazione viene invocato unicamente il metodo Inizialize con i due input come
suoi argomenti di ingresso (Inizialize verrà descritto a breve)
2. Logger (SPWeb destinationWeb, String feature, String logName)
Questo secondo costruttore, invece, setta la variabile privata logName con il parametro di
ingresso, per poi operare come quello precedente.
Comprende inoltre un insieme di metodi atti a creare la lista di log, scrivervi al suo interno e
gestirne gli item al suo interno.
3.3.2.1.1.1.1 SPList CreateLogListIfNotExists È il metodo di creazione della lista di log nella site collection SharePoint di nostro interesse. È
un metodo privato.
Senza argomenti in ingresso, pesca dalla variabili globali l’SPWeb, e si collega alla Lista di log.
Se questa non venisse trovata, viene creata una nuova GUID riferita alla nuova lista generata,
e modificata la colonna “title” chiamandola con la costante TITLE_LOG_LIST.
Tutta il metodo sarà poggiato su due try/catch intrecciati tra loro: nel caso di
malfunzionamento di entrambe le sezioni, verrà ritornato un valore null.
3.3.2.1.1.1.2 Void OpenLog È il metodo, privato, che verifica l’esistenza di un item nella lista di log e, se non esistente, crea
un nuovo item, predisponendolo ad una successiva compilazione.
Ha come argomenti in ingresso:
String feature: è il nome da attribuire al log item;
SPList spLogList: è la lista di log
Il metodo opera secondo questo diagramma di flusso semplificato:
57
Figura 21 - Flusso OpenLog
Il tutto viene eseguito con metodi già forniti dalle libraries a disposizione, tranne il metodo
AddAttachmentToSPItem(), appartenente a questa stessa classe, che definiremo in seguito.
3.3.2.1.1.1.3 Void AddAttachmentToSPItem A completamento del metodo precedente, questo va ad associare gli attachments dell’item in
maniera corretta, ripulendoli e portandoli ad un valore inferiore del MAX_LENGTH definito
all’interno della classe. Anch’esso è privato e non ha variabili di input.
Opera nella maniera seguente:
Setta a true gli UnsafeUpdates;
Exists = false
Controllati tutti gli item
Esiste
Exists = true spFeatureLog = listItem
Exists Crea spFeatureLog logName != null
url dei possibili attachments Attachments
logFile.length > MAX_LENGTH
spLogItem.Attachments.DeleteNow(logName)
AddAttachmentToItem()
VERO
VERO
VERO
VERO
FALSO
FALSO
FALSO
FALSO
FALSO
VERO
58
Recupera la Collection di Attachments associata all’item;
Verifica la presenza del logName: in caso affermativo crea una stringa defLogName con
quel valore
In caso contrario, definisce defLogName con valore la data formattata;
Viene aggiunto un Attachment con i parametri di pertinenza;
Viene recuperato l’SPFile associato al log e settato come spLogFile;
Setta a false gli UnsafeUpdates
3.3.2.1.1.1.4 Void Initialize È il metodo invocato dal costruttore, creando l’ambiente adatto alla verifica ed alla
generazione della log list all’interno della site collection selezionata.
Ha due argomenti in input:
SPWeb web;
String feature.
Ed opera in maniera molto semplice:
1. Viene recuperata la stringa dell’url del web passato;
2. Vi si accede in modalità elevated privileges, creando un nuovo site;
3. Vengono settati all’interno di quest’ultima i permessi per gli UnsafeUpdates;
4. Viene invocato il metodo CreateIfNotExists()
5. Viene dunque verificata l’effettiva presenza (o creazione) della lista: in caso
affermativo, viene avviato OpenLog(feature, spLogList), così da essere predisposti alla
compilazione di un item;
6. Viene dunque revocato il permesso agli UnsafeUpdates
L’utente sarà così abilitato alla compilazione dell’item di pertinenza per quella exception o
informazione che risulterà necessaria in fasi successive di analisi prestazionali.
3.3.2.1.1.1.5 String LogLine È un metodo privato, che ritorna il contenuto da passare agli item nel campo di descrizione.
Suddivide in tre possibili tipi di notifiche: ERROR, WARNING, INFO, definendo una variabile
pubblica enum nella classe stessa.
59
La stringa di ritorno sarà così strutturata: <DateTimeAttuale> + <TipoNotifica> + <Messaggio
Personalizzato>.
3.3.2.1.1.1.6 Void Write È il metodo che va a popolare l’SPFile associato al log. Ha come argomenti di ingresso:
LOG_TYPE type: è il tipo di log che verrà generato;
String message;
Dopo aver dato i permessi agli UnsafeUpdates, viene aperto uno stream sull’spLogFile
esistente, dunque uno StreamWriter su quest’ultimo.
Dunque viene identificato il punto in cui iniziare a scrivere (tramite il metodo Seek), e scritta la
riga di interesse tramite il LogLine. Dopo aver ripulito sia lo StreamWriter che lo Stream
tramite il relativo metodo flush (svuotando il buffer associato a questi), e salvando il
BinaryStream nell’SPFile, viene completata l’operazione.
3.3.2.1.1.1.7 Int AttachmentsLogComparator È un metodo accessorio utile per il clearAttacchments (che descriveremo subito dopo), in cui
viene eseguita la comparazione temporale tra due SPFile, e la loro data di ultima modifica.
Presi A e B due SPFile, verrà ritornato:
-1 se A.TimeLastModified < B.TimeLastModified;
0 se A.TimeLastModified = B.TimeLastModified
1 altrimenti
3.3.2.1.1.1.8 Void ClearAttachments Questo metodo verifica e rimuove gli attachments in eccesso, rimuovendo quelli che
risulteranno i più vecchi.
Il metodo ha una unica variabile di ingresso: l’int maxNumAttachments, che determina, come
dice il nome stesso, il numero massimo di di Attacchments associati al log.
Recuperati gli attachments associati all’item di interesse, verifichiamo se il numero di questi
superino il numero massimo imposto di attachments. Se superiore, vengono recuperati tutti
gli item, riferiti all’interno di una Lista di appoggio spFileList.
60
Su spFileList viene eseguito un sorting che ha come metodo di comparazione
l’attchmentsLogComparator definito poco sopra, e, completato questo, vengono eliminati
quelli che sono i valori più vecchi nella lista, invocando il delete().
Importante sottolineare che il metodo Delete() non rimuove il riferimento nella lista, ma
propriamente l’SPFile associato, in modo tale da rimuoverlo pure all’interno degli Attachments
dell’spFeatureLogItem.
3.3.2.1.1.1.9 void Close Senza argomenti nella signature, fa il Dispose del web utilizzato, rilasciando tutte le risorse non
utilizzate.
3.3.2.1.1.2 Class LogExceptions Questa seconda classe della sezione poggia direttamente su Logger, invocandone
sistematicamente metodi e costruttori per poter gestire in maniera ordinata e vincolata tutte
le funzioni garantite.
Esistono due metodi fondamentali, il LogMessage ed il ManageException, che strutturano, in
maniera differente, il logger a disposizione, supportati da alcuni metodi accessori.
3.3.2.1.1.2.1 Void Alert Metodo di generazione di alert, che vada a visualizzare un messaggio predefinito, sotto forma
di popup, nella pagina in cui si è verificato l’errore.
3.3.2.1.1.2.2 Void LogMessage In questo metodo viene generato un nuovo Attachment legato al log.
Come parametri di ingresso abbiamo:
SPWeb web;
String message: il messaggio da salvare;
String featureName: è il nome della feature che ha generato il log;
Int maxAttachments: il numero massimo di attachments che può avere il log associato;
Logger.LOG_TYPE level: è il tipo di log da generare
Il metodo si limita ad invocarne altri:
1. Inizialmente invoca il costruttore di Logger, con i parametri necessari
61
2. Creato l’oggetto log, ne invoca i metodi Write, ClearAttachments e Close in sequenza
Effettua anche l’overload, senza la variabile LOG_TYPE: in questo modo, viene pre-impostato
che il log si di error.
3.3.2.1.1.2.3 Void ManageException Strutturato in maniera similare al LogMessage, si differenza del precedente inserisce due righe
di log all’interno dell’attachment, una che descrive classe e funzione che hanno generatore
l’eccezione, e la seconda l’eccezione stessa.
Come parametri aggiuntivi, rispetto a LogMessage, difatti ha due stringhe className e
functionName, inserite direttamente dal metodo invocante per descriverne l’origine.
3.3.2.1.1.2.4 Void ManageExceptionGenericAlert Quest’ultimo metodo di classe invoca i precedenti ManageException e Alert, per fornire sia un
messaggio nel log che un pop up in uscita.
3.3.2.1.2 Security La sezione di Security permette una gestione maggiormente efficace dei permessi forniti per
l’utente all’interno della piattaforma SharePoint, fornendo dei metodi di assegnazione e di
rimozione di tali nella site collection.
Le security all’interno di SharePoint hanno una profonda importanza per tutta l’ambiente,
poiché sono definibili ed impostabili a qualsiasi livello, dalla web application, scendendo per la
site collection, le pages, le liste e le document Libraries, fino ad arrivare al singolo item,
consentendo un accesso e diritti di creazione, editing, rimozione e visualizzazione in ogni più
minimo particolare.
Introducendo brevemente le funzionalità dei permessi, come già visto nella creazione di gruppi
utenti, questi possono essere attribuiti a singoli utenti (pescati dall’Active Directory se attivata
unicamente la Windows Authentication, oppure tramite oAuth o una claim-based
authentication, oppure ancora direttamente da un database di credenziali personalizzato), a
zero o più gruppi (popolati con le utenze), ed essere di tipo diverso, a seconda delle
autorizzazioni che si vogliono concedere.
62
L’ambiente12 propone di default cinque livelli per i team sites (quelli che sono solitamente i
template più utilizzati in ambito aziendale per la produzione di site collections) e innumerevoli
permessi specifici da poter configurare.
Per essere chiari, nella prossima parte della trattazione definiremo Securable tutti quegli
elementi di SharePoint cui è possibile applicare dei criteri di visibilità puntuale, che essi siano
item, list, document library, e via dicendo.
Dunque, nel caso dei livelli, si passa da:
Limited Access, in cui l’utente / gruppo ha unicamente diritto di accesso alle risorse
condivise (è un particolare livello, perché si tende ad utilizzarlo per sgranarne meglio i
permessi della stessa utenza in casi più specifici, definendo caso per caso, Securable per
Securable, il tipo di autorizzazione concessa);
Read, in cui l’utenza può leggere i contenuti del Securable autorizzato;
Contribute, in cui è possibile, oltre alle autorizzazioni precedenti, creare items
all’interno di Lists e Document Library
Design, in cui l’utenza, assieme ai permessi del Contribute, può modificare le pages e
approvare gli items generati da altre utenze;
Full Control, in cui l’utente / gruppo può compiere qualsiasi operazione sul Securable
preso in considerazione.
Questi livelli permettono di avere una sgranatura abbastanza ampia degli user all’interno della
web application presa in considerazione, ma nel caso avessimo bisogno di una più
approfondita suddivisione dei ruoli, vi è la possibilità di configurare, uno ad uno, tutti i
permessi concessi e distinti, personalizzati per ogni tipo di Securable disponibile.
Altro tema toccato all’interno di questa sezione, è la protezione di contenuti sensibili privati,
come ad esempio password all’interno di liste di configurazione. Non è sufficiente togliere i
permessi di view sull’item stesso, perché nel caso di utilizzo di questa per determinate
funzionalità, non risulterebbe utilizzabile. Dunque si può preferire l’inserimento di un sistema
di codifica e decodifica di questi contenuti, con due metodi ad hoc.
12
http://technet.microsoft.com/it-it/library/cc721640(v=office.14).aspx per maggiori approfondimenti sul tema dei permessi in ambiente Sharepoint 2010
63
Andiamo ora in descrizione delle due classi sviluppate, una chiamata Permissions, l’altra
EncodeDecode, in modo da vederne le funzionalità implementate.
3.3.2.1.2.1 Class Permissions Vi sono 4 metodi (in overload) per la gestione degli Assignments, mentre 2 per la rimozione di
tutti i permessi.
3.3.2.1.2.1.1 Bool Assign Metodo che permette l’assegnazione dei permessi rispetto un item od una lista rispetto ad
una determinata utenza, o gruppo. Restiuisce true nel caso siano assegnati i permessi
direttamente al Securable indicato, false in caso contrario.
Ha 4 overload, con unico argomento comune l’SPPrincipal, che è la property che users, groups
e ad Users hanno condivisa, mentre si differenziano per il tipo di Securable da autorizzare
(SPList o SPListItem), e dalla modalità in cui viene definito il permesso (SPRoleType o
SPRoleTypeDefinition).
Al posto di Securable può essere inserito a scelta un item o una list (la stessa document library
può essere trattata, in questa situazione, come tale), cosicché tutti gli overload siano descritti
in maniera completa.
La struttura generica del metodo è così descrivibile:
64
Figura 22 - Flusso Assign
3.3.2.1.2.1.2 Void DeleteAll In maniera similare al precedente, vi sono 2 metodi in overload, uno per gli items, uno per le
liste, che vanno a dissociare i permessi già impostati.
Avendo come parametro di ingresso, a seconda del caso, SPList oppure SPListItem, invoca il
metodo BreakRoleInheritance(false), che va a eliminare l’ereditarietà dal padre del Securable
e, tramite il boolean false, rimuove pure quelli che erano fino a prima i permessi associati.
3.3.2.1.2.2 Class EncodeDecode Questa seconda classe di security, come già descritto in precedenza, agisce sull’encoding e
decoding di stringhe, fornendo rispettivamente un metodo per i due casi.
SPRoleAssignment = new SPRoleAssignment(spPrincipal)
SPRoleType
SPRoleDefinition = […].RoleDefinition.GetByType(spRoleType)
SPRoleAssignment.RoleDefinitionBindings.Add(SProleDef)
Permessi specifici per il Securable
Securable.RoleAssigments.Add(SpRoleAssignment)
Return true
Return false
VERO
VERO
FALSO
FALSO
65
La classe importa il namespace System.Security.Criptography13, che permette propriamente la
gestione di codifica e decodifica dei dati in maniera protetta all’interno della site collection
associata.
I metodi indicati si rifanno all’algoritmo di Rijndael, che è la specifica di implementazione
dell’AES, Advanced Encryption Standard, usato come algoritmo standard dal governo degli
Stati Uniti, e di cui faremo un approfondimento in appendice.
Costante privata nella classe, e di rilevante importanza, è IV, stringa di inizializzazione del
vettore di codifica dell’algoritmo.
3.3.2.1.2.2.1 String Encode Il metodo di encoding, poiché basato su di un metodo di cifratura a blocchi, necessita della
definizione della dimensione del blocco da utilizzare durante la crittografia, e della dimensione
della chiave da usare. Per essere aderente allo standard AES, vengono imposte entrambe le
dimensioni a 128 bit.
Parametri di ingresso sono:
String S: è la stringa da convertire;
String key: è la chiave da usare per la crittazione.
Il tutto si basa sulla creazione di un oggetto RijndaelManaged chiamato rjm, in cui vengono
definiti le properties:
Property Value
KeySize 128
BlockSize 128
Key ASCIIDecoding.ASCII.GetBytes(key)
IV ASCIIDecoding.ASCII.GetBytes(IV)
Dunque viene generata lo stream di input, convertendo in formato UTF-8 la stringa in ingresso,
salvandola dunque all’interno di un byte[].
Ora avviene l’encoding vero e proprio: rjm invoca il createEncryptor, e passa lo stream di input
per convertirlo in un nuovo array di byte di output.
13
http://msdn.microsoft.com/it-it/library/system.security.cryptography(v=vs.80).aspx
66
A chiusura, l’output viene convertito dall’array in una stringa Base64, così da avere il return di
interesse.
3.3.2.1.2.2.2 String Decode In maniera similare a ciò che è stato definito in precedenza, questo metodo esegue il decoding
di una stringa generata da Encode.
Ha le stesse variabili di ingresso, necessita di un RijndaelManaged con uguali properties,
variano solo le attività da svolgere sulla stringa di input:
Converte la stringa da Base64 in un array di byte;
Rjm invoca il metodo di Decoding, restituendo un nuovo array di byte;
Quest’ultimo viene convertito in una stringa in formato UTF-8, così da avere il valore
effettivo dell’encription.
67
3.4 Feature BlockUsers
La seconda feature della solution ha importanza per la gestione delle fasi di manutenzione
della site collection su cui questa viene attivata. Ci garantisce difatti il blocco degli accessi a
tutte le pagine della site collection quando non si risultasse appartenenti al gruppo degli
amministratori di tale.
Al suo interno viene importato il modulo BlockedUsers, che di conseguenza va a pescare l’ascx
BlockUsers.ascx a disposizione nella solution.
È importante analizzare il funzionamento dell’xml di BlockedUser e di BlockUsers.ascx.cs per
capire il funzionamento di tale feature.
3.4.1 BlockedUsers/Elements.xml
Il codice di questo file è molto ridotto, ma compie il ruolo fondamentale di delega di un
controllo alla source di interesse.
Difatti, tramite
Setta il controllo di delega degli accessi a tutte le pagine (tramite l’associazione dell’id
GlobalNavigation) alla source ascx BlockUsers, che avrà i suoi metodi di controllo per verificare
l’utenza che ne richiede l’accesso.
Utile constatare che tale ascx viene caricato in automatico al deploy della solution nella
piattaforma, ma risulterebbe inutilizzabile ed inutile, se non nel caso di associazione come
“filtro” per le utenze aventi diritto di modifica nel momento di manutenzione della site
collection.
68
3.4.2 BlockUsers
La funzione dell’ascx in questione è molto limitato, ma risulta efficace nel caso in cui abbiamo
descritto all’inizio della sezione.
È tutto concentrato all’interno del PageLoad associato:
Figura 23 - Flusso BlockUsers
69
4 Implementazione del framework
Questa terza sezione del documento va a trattare una possibile implementazione del nostro
prodotto all’interno di un effettivo sistema informativo.
Ciò è utile per dimostrare come il framework possa essere posto a base di un progetto
generico per fornire supporto allo sviluppatore, sia a livello logico che a livello di
programmazione.
Andremo dunque ad analizzare un prodotto conseguente del framework in modo da mostrare
come questo possa essere usato, procedendo con una descrizione dei requisiti e delle
specifiche di progetto, per poi approfondirne una porzione del flusso per mostrare i vari
frammenti più interessanti.
Si evidenzia il fatto che questa parte di trattazione prenderà solo poche delle funzioni andatesi
ad implementare nel capitolo precedente, poiché non tutti i metodi sono stati utilizzati
all’interno dell’esempio in questione.
4.1 Esempio di progetto
4.1.1 Scopo
La struttura dell’ufficio analizzato è “owner” del processo di gestione delle convenzioni. Tale
processo è suddiviso in una serie di fasi consecutive ma che prevedono alcuni ricicli interni per
approvazione e/o raccolta documentazione aggiuntiva.
La forte necessità di avere un’applicazione a governo di tale processo è giustificata dalla
necessità di mantenere il raccordo ed il coordinamento delle richieste che provengono
dall’esterno e sono traversali. Il sistema si deve fare carico di raccogliere tutte le informazioni
in ogni fase del processo e di consentire un’agile gestione di queste. Oltre a gestire lo storico
del processo nel tempo.
4.1.2 Ruoli nel sistema
Nel processo sono coinvolti attori con diversi ruoli. Ogni attore accede all’applicazione per la
consultazione dello stato dei processi di propria competenza, ed eventualmente ne legge il
dettaglio, esegue operazioni ed inserisce nuova informazioni.
70
Questi sono i ruoli proposti:
Ruolo Sigla Note
Agenzia AGN Gruppo cumulativo che raccoglie tutte le agenzie. Ogni
agenzia avrà a disposizione le stesse funzionalità ma vedrà
solo le informazioni di processo relative alle proprie richieste
di Convenzionamento.
Area Manager AM Tipologia di utenza a capo dei vari livelli di Manager.
Nell’ordine Regional Manager, Manager di Zona. Possono
aprire richieste di convenzione selezionando un’agenzia, e
vedono tutte quelle della gerarchia dei manager di cui sono
responsabili ma non possono modificare queste richieste.
Regional Manager RM Tipologia di utenza, sotto l’Area Manager, a capo dei restanti
livelli di Manager. Nell’ordine Manager di Zona e Assistant
Manager. Possono aprire richieste di convenzione
selezionando un’agenzia, e vedono tutte quelle della
gerarchia dei manager di cui sono responsabili ma non
possono modificare queste richieste. Non vengono coinvolti
come approvatori di richieste che invece coinvolgono i
Manager di Zona/Assistant Manager.
Manager di zona MZ Gruppo cumulativo che raccoglie tutti i manager di Zona.
Ogni manager ha le stesse funzionalità a disposizione. Ogni
MZ riceve e valuta le richieste di convenzione relative alle
Agenzie/Aziende e può inserirle per conto di.
Fabbriche Prodotto FP Si prevedono più gruppi con ruolo FP, in funzione delle
proprie aree di competenza. Ognuno di questi gruppi avrà a
disposizione le sole funzionalità previste per questo ruolo e
vedrà solo le pratiche in cui sono stati coinvolti come gruppo.
Altre Fabbriche AF Hanno ruolo identifico alle FP solo che si occupano di
valutazioni delle condizioni per altre componenti (Marketing
ecc.)
71
Convezioni &
Partnership
C&P Gruppo unico che contiene il personale di C&P preposto a
governare il processo all’interno dell’applicativo. Tutte le
informazioni saranno visibili. Anche C&P può inserire delle
richieste di convenzionamento. La valutazione delle stesse
avviene in autonomia come per la Direzione.
Amministratori
Gruppo unico di sistema.
4.1.3 Fasi del processo
Di seguito vengono elencate tutte le fasi del processo con i relativi ruoli che sono responsabili per quella fase. Le fasi qui descritte riepilogano le fasi tracciate a sistema.
Fase Nr Owner Descrizione
Invio Richiesta
Convenzione
1 Agenzie
MZ
Direzione
C&P
Inserimento a sistema della Richiesta di
Convenzione
Valutazione Richiesta 2 MZ
DIR
C&P
Valuta la pertinenza della richiesta ricevuta da
Agenzia/Azienda. Se positiva inserimento
informazioni di business
Valutazione Proposta
&
Ingaggio Fabbriche
3 C&P Valuta la richiesta pervenuta da MZ/DIR/C&P
Prevede anche l’inserimento di info
aggiuntive che C&P richiede tramite canali
extra sistema come mail & telefono. Se la
valutazione è positiva C&P ingaggia le FP per i
Prodotti legati alle componenti di offerta e le
AP per le altre Componenti.
Valutazione Condizioni
Fabbriche Prodotto
4A FP Ogni FP può essere chiamata a valutare le
condizioni per uno o più prodotti legate alla
convenzione. Per ogni prodotto FP esprime
una valutazione positiva/negativa con
inserimento di informazioni di dettaglio
72
(sconti, deroghe, ecc..) che arricchisce con
note e allegati. È una fase che può svolgersi in
parallelo a fronte degli ingaggi per ogni FP.
Valutazione Condizioni
Altre Fabbriche
4B AF Ogni AF può essere chiamata a valutare le
condizioni per una o più componenti
generiche legate alla convenzione. Per ogni
componente per cui è ingaggiata una AF
esprime una valutazione che arricchisce con
note e allegati. è una fase che può svolgersi in
parallelo a fronte degli ingaggi per ogni AF.
Monitoraggio Esito
Valutazioni
5 C&P In questa fase C&P monitora le valutazioni
delle Fabbriche e può richiedere nuove
valutazioni che possono essere anche
modifiche di valutazioni già richieste.
Definizione & Conferma
Convenzione
6 C&P A seguito del completamento delle
valutazioni C&P approva le valutazioni sulle
componenti che ritiene di inserire nella
convenzione. L’approvazione implica la
generazione automatica del documento di
Convenzione che deve essere inviato al
richiedente per firma.
Convenzione Firmata 7 Richiedente Viene inserita la convenzione ricevuta da C&P
firmata dal referente.
Convenzione Emettibile 8 C&P A fronte della Convenzione firmata C&P
approva la convenzione e la rende
“emettibile”. Da questo momento la
Convenzione è valida e viene notificato agli
attori interessati.
Economics Produttività
Convenzione
9 C&P/Agenzia Fase vincolata al tempo di validità della
Convenzione. In questo punto vengono
73
raccolte, ad intervallo trimestrale
(parametrico), le evidenze di produttività
economica di una singola convenzione. Tale
fase rimane “aperta” fino alla
scadenza/chiusura della convenzione.
Scadenza/Chiusura
Convenzione
10 C&P Quando una convenzione viene chiusa o
giunge a scadenza in questa fase viene
stabilito se la Convenzione rimane valida e
quindi la si proroga oppure si conferma la sua
chiusura indicando una motivazione.
4.1.4 Requisiti funzionali
4.1.4.1 Ruoli ed autorizzazioni di processo
I ruoli previsti dal processo sono quelli indicati nella tabella precedente. Esistono però dei
vincoli ed associazioni di utenze di dettaglio. Riepilogate nei paragrafi successivi.
4.1.4.2 Permessi e funzionalità per attore
Di seguito il riepilogo dei permessi su ogni singola richiesta di convenzione in funzione di ogni
attore.
Legenda permessi:
- I (insert/edit): inserimento/modifica dati;
- A (approve): approvazione fase;
- R (read): lettura dati;
- - : nessun permesso di visibilità sui dati;
Ruoli 1 2 3 4A 4B 5 6 7 8 9 10
AGN R,I,A R - - - - - R,I,A R R,I,A R,I,A
AM R,I,A R,I,A R - - - - R R R R
RM R,I,A R,I,A R - - - - R R R R
MZ R,I,A R,I,A R - - - - R R R R
AMZ R,I,A R,I,A R - - - - R R R R
DIR R,I,A R,I,A R - - - - R R R R
74
FP R R R R,I,A - - R R R R R
AF R R R - R,I,A - R R R R R
C&P R,I,A R,I,A R,I,A R R R,I,A R,I,A R R,I,A R,I,A R,I,A
4.1.4.3 Permessi e visibilità per competenza richieste
Di seguito la tabella riepiloga la visibilità ad alto livello delle richieste di convenzione.
Differenziando i perimetri di competenza tra:
- Proprie richieste: quelle inserite dal singolo attore
- Richieste di sottoposti: visibilità delle richieste inserite da attori gerarchicamente
sottoposti;
- Tutte le richieste: tutte le richieste indipendentemente dal contesto;
- Richieste di competenza: visibilità delle richieste per cui l’attore viene coinvolto nel
processo;
Ruoli
Proprie
Richieste
Richieste
sottoposti
Tutte
richieste
Richieste
competenza
Tutte
Convenzioni
AGN X - - X X
AM X X - - -
RM X X - - -
MZ X X - X -
AMZ X - - X -
DIR X - - X X
FP X - - X X
AF X - - X -
C&P X - X X X
4.2 Progettazione del flusso
Dai requisiti e dalle successive specifiche si è andati a tracciare un diagramma di flusso, che
vada a descrivere il funzionamento delle varie fasi di progetto. Questo lo si può trovare
descritto all’interno dell’Appendice B.
75
4.3 Suddivisione per macrofasi
Lo step successivo è quello della strutturazione per macrofasi del workflow. È importante
definirne le caratteristiche operative e categorizzare le fasi in sezioni distinte.
Analizzando i parametri proposti nei punti 4.1.2, 4.1.3, 4.1.4, si è giunti a dividere il workflow
in tre macrofasi:
Macrofase Monitoraggio richieste: comprendenti le prime tre fasi, questa permette
la creazione e la gestione delle richieste di convenzioni, fintantoché queste non
vengono inviate al vaglio delle fabbriche di interesse;
Macrofase Quotazioni: comprendente le fasi 4 e 5, porta all’analisi delle richieste,
da parte delle fabbriche di pertinenza, perché le approvino o modifichino in step
successivi;
Macrofase Convenzioni: è la fase di strutturazione ed approvazione definitiva della
convenzione, e vi permane fintantoché questa risultasse valida oppure venisse
annullata. Copre le restanti fasi.
4.4 Analisi di sviluppo del progetto
Per completare la descrizione del progetto d’esempio, andiamo a
descrivere le modalità di creazione delle varie fasi. Per non
dilungarci troppo sulla stesura del codice di tutto il progetto, si è
optato di analizzare solamente una macrofase (nel nostro caso, la
prima) e verificare il passaggio da una macrofase alla successiva.
Sottolineiamo il fatto che vengono tralasciate (ma trattate in caso
esemplificativo nell’appendice) le operazioni di creazione delle
features per l’attivazione delle strutture dell’intero del sistema
informativo, per non dilungarci su un ramo che non riguarda
direttamente la trattazione del documento in questione.
Figura 24 - Flusso d'esempio analizzato
76
Figura 25 - Organizzazione strutturale della Macrofase 1
4.4.1 Definizione delle liste
Definire le liste da utilizzare all’interno di un workflow generico diviene impossibile, poiché
ogni flusso ha i suoi task.
Possiamo però andare a descrivere con quali possibili modalità queste vengano strutturate,
sottolineando quali siano i campi necessari per collegare le varie fasi.
4.4.1.1 Descrizione via Metodo
Nel caso di liste che richiedano campi standard, è possibile sfruttare uno dei metodi proposti
nella seconda parte del progetto: si veda 3.3.1.1.1.
77
Template da selezionare
Nome dell’Item da creare
Figura 26 - Creazione di una lista in VS2010
4.4.1.2 Descrizione via XML
Nel caso di liste che vadano a sfruttare dei campi custom, invece, l’unica via percorribile è
quella della generazione tramite XML della struttura dati, poiché il metodo citato in
precedenza non permette la gestione di campi non di default.
Per sfruttare questa modalità all’interno di Visual Studio 2010, nella solution di interesse, sarà
da generare una nuova List Definition.
4.4.1.3 Caratterizzazione della lista
Il nostro caso propone la creazione delle liste (una effettiva, ed una di appoggio) tramite XML,
proprio poiché vengono utilizzato dei campi custom.
Alla creazione della nuova lista, nominata RichiesteListDefinition, avremo due elementi distinti
da modificare: elements.xml e Schema.xml.
Il primo è la definizione nominale e funzionale della lista stessa:
78
Figura 27 - Definizione della lista
Al cui interno vengono definiti primariamente il rispettivo nome, quello da visualizzare e la sua
descrizione. Non vi sono ulteriori elementi di importanza.
L’altro file andatosi a generare, invece, è quello dello Schema, e permette la descrizione
strutturale dei campi, con definizione degli stessi.
In questo caso, è importante mantenere identici all’elements.xml i vari titoli e coincidenze.
Elementi da evidenziare nella strutturazione della lista sono i seguenti:
Figura 28 - Schema.xml content type
Nella prima parte del codice, vengono definiti i FieldRef, che “Specifies a column to
reference in this content type” per Microsoft, e dunque anticipano quelli che saranno in
seguito definiti i campi all’interno della tabella;
79
Figura 29 - Definizione dei campi
Secondo step da tenere in considerazione è la definizione dei campi nei loro particolari,
richiamati tramite il Field ID ed il Name: in questa parte vengono definite le
caratteristiche sul tipo, sul display Name, sulla modificabilità del campo stesso e sulla
necessità del campo, più tutte le caratteristiche accessorie nel caso di type particolari
(nell’immagine sopra, ad esempio, essendo dei campi che vanno a pescare dall’Active
Directory gli utenti, posso definire o meno se associarvi solo un’utenza oppure anche
un gruppo di utenze);
Ultimo elemento da definire è quello della view della lista (una o più, a seconda
dell’interesse). Definendone il nome della vista, la struttura in visualizzazione e la
possibilità di visualizzazione su mobile, poi si possono indicare, ripescando i FieldRef del
punto 1, quali siano i campi visibili all’interno di questa opzione: solo quelli elencati
all’interno di questa parte potranno essere accedibili (sia che siano modificabili oppure
solamente visibili) all’utente. Inoltre, si possono applicare query all’interno della stessa
vista, con elementi che possano risultare interessanti al cliente (ad esempio,
ordinamento per creazione dell’elemento).
80
Figura 30 - Definizione della view della lista
Figura 31 - Definizione delle query applicate alla lista
In questo modo, la lista creata avrà a disposizione tutti i campi (custom o meno) necessari
nella macrofase.
4.4.2 Definizione dei permessi
Il secondo passaggio avviene all’interno di un render, in maniera dinamica. All’accesso della
form, il sistema andrà a fare una query sui vari campi disponibili, e la relativa fase di
appartenenza:
Figura 32 - Verifica della fase di un campo
Andando così a ridurre l’insieme delle colonne da verificare. Lo step successivo sarà dunque
quello di verificare l’accessibilità di questi campi da parte dell’utente di pertinenza, e lo stato
della fase (edit o display), in modo tale da gestire di conseguenza i campi disponibili.
81
Figura 33 - Verifica di stato
4.4.3 Creazione dell’item
Una trattazione dedicata è quella della creazione dell’item della richiesta.
Bisogna sottolineare il fatto che andranno ad incrociarsi i metodi di gestione della lista, con il
relativo event receiver, e quella del render della form:
Alla domanda di inserimento di una nuova richiesta, il processo attiverà l’event receiver
associato alle richieste, ed attiverà l’itemAdding:
Figura 34 – Parziale descrizione dell’itemAdding di nuova richiesta
82
Questo avverrà immediatamente prima dell’effettiva creazione fisica dell’item, in modo tale
che il metodo dinamico del form sia funzionante: in questa fase infatti verrà definito univoco
l’id della richiesta.
Nell’itemAdded, invece, verranno popolati, a seconda dell’utenza e del gruppo, i campi fissi
della prima fase, e rotti i vincoli di permessi esistenti e definiti per le liste, in modo tale da
permettere il funzionamento dell’intero ciclo.
Solo a questo punto andrà ad agire il codice del form, come descritto nel paragrafo
precedente.
4.4.4 Gestione del passaggio di fase
In maniera similare al punto 4.4.2, il comportamento e la gestione del passaggio di fase (sia
che sia da fase 1 a fase 2, ed allo stesso modo dalla 2 alla 3) avviene tramite l’interazione
dell’event receiver con il tabRender, con, in questo caso, l’interessamento di itemUpdating e
itemUpdated.
Il passaggio di fase, inoltre, contempla anche l’invio delle mail di pertinenza, tramite l’utilizzo
dei metodi proposti in 3.3.1.5 e quelli della creazione dei documenti di 3.3.1.1.
4.4.5 Gestione dei passaggio di macrofase
Arrivati al completamento della fase 3, il sistema avrà due possibili avanzamenti: approvazione
della richiesta, e successivo passaggio alla fase 4, oppure rifiuto della stessa e conseguente
chiusura della pratica con ingresso in fase 10.
Per la chiusura di pratica, l’operazione che verrà svolta è molto limitata:
Figura 35 - Invio mail e chiusura pratica
83
Verrà inviata una mail di notifica a chi di pertinenza (agenzia richiedente e i diversi manager) e
verrà mandato il valore della fase a 10, così da poter mettere in archivio la fase stessa, ma
questi ultimi sono passaggi che andrebbero ad appesantire la trattazione distaccandosi dalla
tematica cardine, quindi tralasceremo questa parte di trattazione.
Nel caso invece la richiesta venisse approvata a sistema, verrà scatenata tutta una serie di
procedure per l’accesso alle fasi successive:
Vengono definiti nuovi permessi per l’agenzia richiedente:
Figura 36 - Generazione nuovi permessi
Vengono definiti in cascata i nuovi permessi per tutti i ruoli connessi all’agenzia
richiedente;
Viene generato il nuovo item, all’interno della lista ingaggi,
Figura 37 – Creazione dell'item (descrizione parziale)
con i parametri acquisiti nelle fasi precedenti e necessari alla corretta computazione in
quelle successive (pur comunque evitando elementi di ridondanza non necessari)
84
Figura 38 - Popolamento dei campi di interesse
Dunque, a concludere la fase, come per quelle precedenti, tramite il framework
vengono inviate le mail di conferma di progresso di fase a coloro che ne fossero
interessati e coinvolti.
Otterremo così dunque una sequenzialità degli elementi inseriti all’interno delle varie liste, con
referenze per poterle legare tra loro, permettendo dunque la gestione condivisa dei dati
all’interno delle macrofasi di pertinenza.
4.4.6 Creazione dei gruppi
A concludere la trattazione di questo capitolo, può essere interessante analizzare la
strutturazione dei differenti gruppi, che vanno a ricoprire le fasi dei ruoli e delle relazioni tra i
differenti operatori all’interno del sistema informativo d’esempio.
Com’è precisato nel punto 4.1.2, i vari utenti dell’applicativo sono suddivisi in gruppi
gerarchici, tra cui vi sono differenti relazioni esistenti, fondamentali per la corretta
distribuzione dei permessi durante il workflow di una richiesta.
L’importanza dunque è generare, in ordine preciso, le strutture che permettano di definire
gruppi, utenze e legami stessi. Solo alla completa strutturazione delle relazioni presenti, il
workflow potrà funzionare in maniera adeguata.
Andando a pescare dai metodi sviluppati per il framework, quindi, avremo:
4.4.6.1 Generazione dei gruppi
Il processo si divide in due fasi:
85
la prima sarà quella di verifica dei gruppi pre – esistenti e di quelli necessari al
funzionamento;
Figura 39 - Verifica dei gruppi presenti
Nella seconda, invece, verranno creati quelli assenti:
Figura 40 - Creazione dei gruppi
4.4.6.2 Generazione degli utenti e dei legami
Gli utenti vengono generati sia a livello di Active Directory (il gestore delle utenze di Windows)
che a livello SharePoint:
Definiti i parametri di accesso all’AD, vengono fisicamente create le utenze con i
rispettivi parametri di configurazione;
86
Figura 41 - Creazione dell'utenza in AD
Dunque le utenze generate vengono distribuite, a seconda dei casi, all’interno dei
differenti gruppi, così da poter essere riconoscibili da SharePoint stesso.
Figura 42 - Inserimento di un'utenza di esempio in un gruppo
A questo punto, andando a generare una lista di appoggio, potranno essere definiti e resi
disponibili a sistema i legami tra le varie classi di utenze, in modo tale da vincolare il percorso
all’interno dell’applicativo a seconda del ruolo che si vada a rivestire. Ad esempio, prendendo
la scala gerarchica dal basso, e quindi dalle agenzie, non avrò modo di determinare chi, tra i
vari “superiori” potranno operare sulla pratica in corso; viceversa, più in alto nella gerarchia mi
ritroverò, più libertà di scelta sugli operatori vi saranno.
Questa stessa lista verrà poi richiamata dai form delle macrofasi per poter legare i dati già
presenti a sistema alla richiesta in corso.
4.5 Conclusione dell’esempio
Abbiamo descritto, senza troppo dilungarsi sui particolari, come il framework possa essere
integrato all’interno di un sistema informativo aziendale. I punti cardine, come già ribadito più
volte, sono:
87
La possibilità di adattabilità del framework implementato al processo di interesse;
La possibilità di utilizzare parte del framework, e parte non utilizzarlo, a seconda di ciò
che si vada a sviluppare;
La possibilità di utilizzare il workflow logico distribuendo in maniera diversa (com’è
possibile vedere dal diagramma di flusso in Appendice B) i carichi e le fasi presenti nel
processo;
La possibilità di estendere il framework a piacere, visto che è un prodotto comunque
espandibile.
La strutturabilità e destrutturabilità del prodotto sono di fondamentale importanza per
l’impianto e l’adattabilità del pacchetto, e sono basilari per l’efficacia del prodotto offerto.
88
5 Sviluppi futuri
Il prodotto così ottenuto risulta già essere operativo e funzionale alla causa per cui è stato
originato, ma può essere certamente espanso a seconda delle nuove funzionalità che possano
risultare necessarie in successivi sviluppi.
Un elemento sicuramente che sarà da tenere in considerazione è quello della migrazione del
framework sviluppato all’interno di SharePoint 2013. Il progetto, nato in ambiente SharePoint
2010, potrebbe risultare non completamente funzionante nel nuovo CMS. Una completa
verifica della compatibilità del prodotto in SP2013 ed un conseguente debug delle funzionalità
divenute corrotte è di fondamentale importanza per un utilizzo futuro del prodotto.
Un’altra possibile implementazione del framework è quella dell’integrazione di un modello
generico per il tema grafico della site collection a cui andrà ad integrarsi: l’orientamento
sempre più custom dei prodotti sviluppati per i vari clienti richiede un’identificazione dello
stesso anche nel sistema informativo utilizzato. Una parametrizzazione delle caratteristiche
standard dell’interfaccia grafica da applicare può essere utile per alleggerire un carico di
programmazione più specifico ma pur sempre ripetitivo nei vari progetti.
89
6 Conclusioni
Questa tesi ha sviluppato un prodotto apprezzato ed efficace da usare immediatamente, con
gli ovvi sviluppi e correzioni successive, all’interno di un’azienda di consulenza come quella
commisionataria.
Questa tesi mi ha permesso di approfondire le necessità che uno sviluppatore di alto livello ha
nel corso della sua vita lavorativa, partendo dall’analisi delle strumentazioni fornite da
Microsoft, in particolare SharePoint e Visual Studio, finendo alla ricerca delle migliori vie per
affrontare le problematiche riscontrate nello sviluppo del workflow. Il risultato ottenuto è atto
ad alleggerire il carico di lavoro di un possibile mio futuro collega, e di conoscere ed
apprezzare quelle che sono le richieste che un cliente standard può portare ad un’azienda di
consulenza.
L’attività così svolta ha preso circa 40 ore per l’apprendimento e l’utilizzo dell’ambiente Visual
Studio e quello di SharePoint Server con le sue specifiche avanzate, come ad esempio la
configurazione adeguata per l’accesso al TFS (Team Foundation Server), l’apprendistato in
prodotti già esistenti (con susseguente analisi delle funzionalità già in precedenza sviluppate in
maniera disparata), la lettura della documentazione pre - esistente di ulteriori progetti, e la
corretta gestione delle strutture del CMS e dell’IDE.
A seguire, approssimativamente altre 60 ore per definire in maniera precisa i requisiti ritenuti
necessari e basilari da implementare, la relativa suddivisione in aree funzionali, e per definire
le caratteristiche e la forma logica del workflow di interesse.
La fase di progettazione ha preso dunque circa ulteriori 60 ore, in cui sono stati definiti i
metodi e le classi da implementare all’interno della library, e allo stesso modo definite le
strutture per lo sviluppo del workflow.
300 ore circa sono servite per la fase di programmazione del framework, sia nelle sua library
che nelle features per l’installazione della stesso all’interno delle site collections; all’interno di
questa fase si può andare a contemplare anche la programmazione del primo progetto di
esempio (sviluppato in team), con cui presentare il prodotto finora sviluppato, e le relative
tempistiche di test.
90
Uno degli elementi da me più apprezzati all’interno di questa tesi è stato quello della ricerca
delle necessità dello sviluppatore tipo, all’interno di un ambiente proprietario come quello
Microsoft, ed in particolare SharePoint: avendo già lavorato in precedenza su questa
piattaforma (pur nella sua versione base, qual è SharePoint Foundation e la sua IDE SharePoint
Designer), è stato un buon punto di analisi introspettiva dei bisogni di colui il quale va ad
approcciarsi non per la prima volta a questo ambiente. La parte dunque più articolata è stata
quella di cogliere, nella miriade di problematiche specifiche, quali fossero quelle più generali e
ripetitive all’interno di un set di aree come quelle proposte e orientate al servizio del workflow
progettato.
Molto importante è stato anche lavorare all’interno di un team, permettendomi di apprendere
i crismi e le criticità che si possono incontrare a crescere e a produrre all’interno di una
squadra, anche numerosa. La generalità del prodotto che si è andati a sviluppare è andato
anche a catalizzare l’interesse dell’ufficio stesso, fornendo una grossa collaborazione e
segnalazione degli elementi che gli stessi colleghi hanno riscontrato come necessari nei vari
progetti seguiti.
Ultimo frangente, non trattato all’interno della tesi, ma a cui è giusto dare importanza, è
quello della fase di test: se in un ambiente di studio come quello universitario la fase di “prova
su strada” è limitata spesso alla sola verifica orientata alla consegna del progetto, in ambiente
lavorativo ho potuto apprezzare (anche sulla mia pelle, aggiungo io), quanto siano importanti
le verifiche funzionali in tutte le varie fasi. Ciò mi ha concesso di apprendere come, a livello
aziendale, i vari testing siano approfonditi e programmati in maniera quasi maniacale, per
evidenziare quanto sia importante questa fase all’interno dello sviluppo di un lavorato come
quello sviluppato da una società di consulenza.
Mi ritengo in conclusione soddisfatto della ricerca effettuata e del prodotto che si è
sviluppato, poiché l’apprendimento e l’approfondimento di un tool a me poco noto come
Visual Studio e di un CMS aziendale come SharePoint Server mi han permesso di apprendere
gli elementi cardine di programmazione in questo ambiente, guadagnando conoscenze in
un’area tematica che, a quanto visto anche durante il periodo di tirocinio e di stesura della tesi
in azienda, fa molta gola a grandi aziende.
91
7 Ringraziamenti
Sono stati sei anni particolari, formativi, tempranti. Potevano essere di meno, ma la sorte ha
voluto che non fossero di più.
Grazie a questo percorso sono indubbiamente cresciuto, sono diventato uomo, prima che
dottore, e non posso che essere grato a ciò che ho imparato ed appreso, agli schiaffi che ho
preso ma anche alle soddisfazioni, piccole e grandi, che mi sono tolto. Un ambiente stimolante
e produttivo come quello universitario si è dimostrato il più adatto banco di prova per sfornare
un futuro cittadino e lavoratore.
Ma questo viaggio non l’ho compiuto da solo, ma è stato costellato di persone che, nei loro
ruoli, lo hanno caratterizzato e accompagnato verso il suo completamento. Anzi, senza queste
persone molto probabilmente sarebbe ad un punto morto, cieco, ed io, molto probabilmente,
sarei rimasto quel ragazzo che, nel 2008, ha cominciato questo cammino.
Proprio per questo sento la necessità di ringraziarle:
Un doveroso ringraziamento va al Professor Ing. Maurizio Fermeglia, che si è mostrato
disponibile a seguirmi nello studio e nella stesura sia della tesi di laurea triennale sia che per
quella magistrale. Allo stesso modo ringrazio il dottor Dario Sottana, per la disponibilità nel
seguirmi durante il lavoro svolto per questa tesi.
Ringrazio i miei genitori, Ornella ed Antonello, e mio fratello Thomas, per la pazienza, la
sopportazione e l’affetto che hanno sempre portato nei miei confronti. A loro dovrò essere
sempre grato per tutto quello che mi hanno dato, e non potrò mai negare loro l’affetto più
profondo.
Ringrazio Giulio e Francesco, compagni di viaggio in questa avventura che è stata l’università,
nei momenti belli e soprattutto nei momenti più difficili, e che dopo questi anni sono diventati
prima di tutto compagni di vita.
Ringrazio Lisa e David, portati dai loro sogni e dalle loro capacità lontani da casa, e fisicamente
lontani da me, ma rimasti più vicini che mai con l’anima, forti dell’amicizia che ci lega da ormai
tanti anni.
92
Ringrazio Nicoletta, Jenny e Giuliana, che con il loro affetto sono riuscite a smuovere e
convincere uno come me a mettersi in gioco e a darmi la forza di affrontare i momenti più
problematici, specie al di fuori dell’ambiente di studio.
Ringrazio Arianna, divenuta nel corso degli anni una sorella, un’amica, una confidente, un
riferimento con cui incontrarsi e scontrarsi, con cui arrabbiarsi ma per poi restare uniti
sempre, legati da un profondo affetto.
Ringrazio i ragazzi con cui ho lavorato presso Reply, ed in particolare Marzia, Diego, Walter e
Mauro, che mi hanno accolto a braccia aperte e accompagnato in questo nuovo ambiente
come un fratello minore.
Ringrazio Costanza, Giulia, Francesco, Riccardo A., Michele, Jan, Sara, Letizia, Riccardo R.,
Gianluca, Daniele, Maria Grazia e Meri, compagni di divertimento in quel fantastico mondo
che è il teatro.
Ringrazio i colleghi arbitri di Trieste e della regione, per avermi aiutato a crescere in un
ambiente competitivo come quello sportivo, ed in particolare come il mondo arbitrale.
E ringrazio, in ordine sparso, Erica, Matteo M., Anna P., Alessandra J., Caterina, Fabrizio,
Mariela, Alessandra L., Roberta, Paolo, Pietro, Nicoletta L., Matteo F., Alice, Diana, Giampaolo,
Diego, Anna B., che hanno fatto parte di questo percorso, ed hanno voluto farne parte.
Non posso che ringraziarvi tutti.
Vi voglio bene.
Alex
93
8 Appendici
8.1 Appendice A – Algoritmi di Crittazione dei dati in .NET
I dati gestiti dalle applicazioni possono essere memorizzati in modo permanente su appositi
supporti o trasferiti attraverso reti. In entrambi i casi essi sono entità molto vulnerabili poiché,
sebbene sia possibile definire opportuni permessi di utilizzo sulle applicazioni, un
malintenzionato con accesso all’hard disk o all’infrastruttura di rete può bypassare la sicurezza
a livello di software ed estrarre informazioni sensibili dai dati o modificare gli stessi.
Per far fronte a tale situazione è possibile utilizzare la cosiddetta crittografia, una tecnica volta
ad assicurare la segretezza e l’integrità sia dei dati memorizzati, sia dei dati trasferirli tramite
applicazioni apposite.
Il .NET Framework fornisce classi per applicare diversi tipi di crittografia14, incluse quella
simmetrica e quella asimmetrica (tralasciando l’utilizzo di codici Hash o di firme digitali).
La crittografia a chiave segreta è quella che utilizza algoritmi estremamente veloci e adatti a
gestire grosse quantità di dati: pur essendo violabili in un tempo polinomiale proporzionale
alla lunghezza della chiave, nella maggior parte dei casi è improponibile. Il più grosso
svantaggio, come è chiaro, è che mittente e destinatario hanno bisogno di conoscere entrambi
la chiave segreta, rendendo cruciale e fortemente rischioso il passaggio di chiave da un utente
all’altro: l’intercettamento della stessa vanificherebbe il processo di crittografia.
La crittografia a chiave pubblica, invece, va ad utilizzare coppie di chiavi, la cosiddetta chiave
pubblica che può essere condivisa, e quella privata, in possesso del solo ricevente. Si basano
sull’utilizzo di funzioni unidirezionali, che non permettono, nota la chiave pubblica, di risalire
alla chiave privata, se non in casi molto rari (le chiavi deboli). A controbilanciare la sicurezza
del sistema, vi è la lentezza degli algoritmi che lo implementano, e le conseguenti
problematiche nella gestioni di grosse moli di dati.
Le principali funzionalità di crittografia del Framework .Net, tra cui l’implementazione di
algoritmi simmitrici e asimmetrici sono presenti nel namespace System.Security.Criptography
14
Per un approfondimento sulla tematica della crittografia a livello teorico, ed in particolare degli algoritmi DES, AES e algoritmi in chiave pubblica, si consiglia la lettura del volume Teoria dell’informazione, codici, cifrari – F. Fabris, Bollati Boringhieri, capitolo III
94
e, a seconda della tipologia di algoritmo, hanno classi che vanno a derivare da quella base
System.Security.Cryptography.SymmetricAlgorithm (caso simmetrico) oppure quella
System.Security.Cryptography.AsymmetricAlgorithm (caso asimmetrico).
Per poter sopperire alle mancanze proposte dalla crittografia simmetrica, si vanno ad utilizzare
gli algoritmi asimmetrici per il trasferimento della chiave segreta, per poi operare in via
segreta senza problemi.
Nel Framework gli algoritmi di crittografia sono implementati nelle classi RijandelManaged
(AES), RC2, DES e TripleDES. Tutte le classi a disposizione andranno a generare una chiave
tramite il metodo <oggetto-algoritmo-prescelto>.GenerateKey(), e dunque, tramite la
struttura proposta dal Framework, il processo di comunicazione diventerà simile a quello di
una lettura e scrittura di un qualsiasi stream standard.
A livello logico, il processo sarà il seguente:
1. Creare un oggetto Stream per interfacciarsi con la memoria o il file da cui si vogliono
leggere o su cui si vogliono scrivere dati;
2. Creare un oggetto appartenente a una delle classi di algoritmi di crittografia simmetrici
3. Specificare la chiave, il vettore di inizializzazione o entrambi per l’algoritmo scelto;
4. Chiamare il metodo CreateEncryptor() o CreateDecryptro() per creare un oggetto
ICryptoTransform;
5. Creare un oggetto CryptoStream utilizzando l’oggetto Stream e l’oggetto
ICryptoTransform definiti in precedenza;
6. Leggere da o scrivere sull’oggetto CryptoStream.
In tal modo sarà possibile implementare uno dei possibili algoritmi di crittazione a chiave
segreta.
Nel nostro progetto, è stato utilizzato quello che è definito come Algoritmo di Rijandel, o
anche noto come AES (Advanced Encryption Standard) di cui approfondiremo l’algoritmo e
l’implementazione nel paragrafo successivo.
95
8.1.1 Algoritmo di Rijndael
L’algoritmo di Rijndael è propriamente una particolare implementazione del cosiddetto
Advanced Encryption Standard (AES), ed è attualmente lo standard di cifratura a blocchi
utilizzato dagli Stati Uniti d’America, subentrando al DES.
Essendo esso stesso l’evoluzione del DES, è stato scelto all’interno del progetto per
crittografare in chiave privata il traffico dati.
Questo nasce come un’evoluzione del cifrario Square, e si dissocia dal DES poiché strutturato
come una rete a sostituzione e permutazione, piuttosto che una rete di Feistel, ma non
coincide precisamente con AES, poiché quest’ultimo ha blocchi di dimensione fissa (128 bit) e
la chiave di 128 / 192 / 256 bit, quando invece Rijndael indica che sia blocco che chiave
debbano essere multipli di 32 bit, tra 128 e 256 bit.
La struttura dell’algoritmo parte con l’utilizzo di una matrice 4 x 4 byte chiamate state, e nel
caso i blocchi crescano, ogni 32 bit viene aggiunta una colonna.
L’algoritmo segue tali operazioni:
1. AddRoundKey: Ogni byte della tabella viene combinato con la chiave di sessione, la
chiave di sessione viene calcolata dal gestore delle chiavi.
Successivamente per cifrare sono previsti diversi round o cicli di processamento: ogni round
(fase) dell'AES (eccetto l'ultimo) consiste dei seguenti quattro passaggi:
1. SubBytes: Sostituzione non lineare di tutti i byte che vengono rimpiazzati secondo una
specifica tabella.
Figura 43 - Rijndael SubBytes
96
2. ShiftRows: Spostamento dei byte di un certo numero di posizioni dipendente dalla riga
di appartenenza.
Figura 44 - Rijndael ShiftRows
3. MixColumns: Combinazione dei byte con un'operazione lineare, i byte vengono trattati
una colonna per volta.
Figura 45 - Rijndael MixColumns
4. AddRoundKey: Ogni byte della tabella viene combinato con la chiave di sessione, la
chiave di sessione viene calcolata dal gestore delle chiavi.
Figura 46 - Rijndael AddRoundKey
97
La struttura così proposta garantisce, come specificato anche dalla NSA (National Security
Agency) una sicurezza sufficiente agli scopi, e scelta in quanto la più flessibile nel trattare
chiavi a lunghezza diversa, per l’agevole implementazione sia per via hardware che per via
software e per le ridotte richieste di memoria. Inoltre, l’AES effettua, a seconda delle chiavi, 10
(128 bit), 12 (192 bit) e 14 (256) round di crittazione.
8.1.1.1 Possibile implementazione in C# Per fornire un esempio pratico dell’applicazione dell’algoritmo di Rijndael, possiamo andare a
creare un’applicazione che legga un file criptato e ne esegui la crittografia, salvando il
risultato.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string inputFile = @"C:\test.txt";
string outputFile = @"C:\test_cif.txt";
FileStream inputStream = new FileStream(inputFile,
FileMode.Open, FileAccess.Read);
FileStream outputStream = new FileStream(outputFile,
FileMode.OpenOrCreate, FileAccess.Write);
SymmetricAlgorithm testAlg = new RijndaelManaged();
testAlg.GenerateKey();
byte[] data = new byte[inputStream.Length];
inputStream.Read(datiFile, 0, (int)inputStream.Length);
ICryptoTransform crypt = testAlg.CreateEncryptor();
CryptoStream cryptStream = new CryptoStream(outputStream,
crypt, CryptoStreamMode.Write);
cryptStream.Write(data, 0, data.Length);
cryptStream.Close();
inputStream.Close();
outputStream.Close();
}
}
}
Il codice qui proposto andrà a generare ogni volta una chiave casuale, e dunque associando lo
stesso file di ingresso avremo differenti risposte in output, e non potrà essere in alcun modo
decrittato poiché non viene memorizzata la chiave (che può essere invece conservata tramite
un semplice BinaryWriter object).
98
8.2 Appendice B – Diagramma di flusso completo del progetto d’esempio
Inserimento Richiesta di
Convenzionamento
Valutazione Richiesta
Nuova Richiesta di Convenzionamento
Richiesta Chiusa
Inserimento Dettagli Economici/ di
Business
Valutazione Positiva
Valutazione Negativa
Invio Richiesta a C&P
Valutazione Proposta
Non di Interesseper AG
Interesse di AG
Ingaggio Fabbriche Prodotto & Altre
Fabbriche
Valutazione Condizioni
FP1
Valutazione Condizioni
FPN………...
Fabbriche Prodotto
Valutazione Condizioni
AF1
Valutazione Condizioni
AFN………...
Altre Fabbriche
MonitoraggioEsito
Valutazioni
ValutazioneRisposta
Richiesta nuova valutazione
Valutazione Negativa
Definizione e Conferma
Convenzione
Valutazione Positiva
Invio convenzione per firma
Convenzione Firmata?
No
Convenzione Emettibile
Tutte Risposte Pervenute
InserimentoEconomcs
Produttività Convnezione
Chiusura Convenzione per
scadenza
99
9 Bibliografia
Jorg Krause, Christian Langhirt, Alexander Sterff, Bernd Pehlke, Martin Doring –
SharePoint 2010 as a Development Platform
Tom Carpenter, James Pyles – Microsoft SharePoint 2010 Administration
Emer McKenna, Kevin Laahs, Veli-Matti Vanamo – Microsoft SharePoint 2010 all-in-one
for Dummies
David Mann, Ted Pattinson, Andrew Connell, Scot Hillier - Inside Microsoft SharePoint
2010 (Developer Reference)
Stephen Cawood – How to do Everything Microsoft SharePoint 2010
Microsoft Office System and Servers Team – Getting Started with Microsoft SharePoint
Server 2010
Microsoft Office System and Servers Team – Deployment guide for Microsoft
SharePoint Server 2010
Microsoft Office System and Servers Team – Technical reference for Microsoft
SharePoint Server 2010
Microsoft Office System and Servers Team – Goverance guide for Microsoft SharePoint
Server 2010
Microsoft - Microsoft SharePoint 2010 Application Developement
http://msdn.microsoft.com/it-it/library/gg145045(v=vs.110).aspx per la trattazione del
framework .Net fornito da Microsoft
http://office.microsoft.com/en-us/SharePoint-server-help/introduction-to-workflows-
HA010154424.aspx introduzione ai workflow
http://en.wikipedia.org/wiki/Workflow
Saikat Mukherjee, Hasan Davulcu, Michael Kifer, Pinar Senkul, and Guizhen Yang -
Logic-Based Approaches to Workflow Modeling and Verification
http://stackoverflow.com/ per un accesso rapido alle principali FAQ in ambiente di
sviluppo software (in generale)
Francesco Fabris - Teoria dell’informazione, codici, cifrari
https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
100
http://msdn.microsoft.com/it-
it/library/system.security.cryptography.rijndaelmanaged.aspx per l’approfondimento
della codifica Rijndael e dell’AES
101
Sommario
1 Introduzione ........................................................................................................................... 3
1.1 Perché Microsoft SharePoint Server 2010 ..................................................................... 4
2 Workflow ................................................................................................................................ 7
2.1 Breve definizione ............................................................................................................ 7
2.2 Workflow in SharePoint ................................................................................................. 7
2.3 Requisiti .......................................................................................................................... 8
2.4 Specifiche ....................................................................................................................... 9
2.4.1 Gestione delle macrofasi ........................................................................................ 9
2.4.2 Gestione del rollback di uno step ......................................................................... 11
2.4.2.1 Stato del task ................................................................................................... 12
2.4.2.2 Stato dei dati ................................................................................................... 12
2.4.2.3 Permessi .......................................................................................................... 13
2.4.2.4 Ruoli nel rollback ............................................................................................. 13
2.4.3 Definizione delle specifiche .................................................................................. 13
2.4.4 Specifiche accessorie ............................................................................................ 15
2.5 Progettazione ............................................................................................................... 16
2.5.1 Gestione dei dati nelle macrofasi ......................................................................... 16
2.6 Scelta della struttura dati ............................................................................................. 17
3 Library SharePoint Utilities .................................................................................................. 19
3.1 Requisiti ........................................................................................................................ 19
3.2 Analisi funzionale ......................................................................................................... 20
3.3 Feature Utilities ............................................................................................................ 21
3.3.1 Classi ..................................................................................................................... 22
3.3.1.1 DocLib .............................................................................................................. 22
102
3.3.1.1.1 SPList Create ............................................................................................... 22
3.3.1.1.2 Void MoveAttFile ........................................................................................ 23
3.3.1.1.3 Void InsertFile ............................................................................................. 24
3.3.1.1.4 Void DeleteFile ............................................................................................ 25
3.3.1.1.5 Metodi di controllo ..................................................................................... 25
3.3.1.1.5.1 File Name ............................................................................................. 25
3.3.1.1.5.2 Path ...................................................................................................... 26
3.3.1.2 Groups ............................................................................................................. 27
3.3.1.2.1 SPGroup Create .......................................................................................... 27
3.3.1.2.2 void CreateIfNotExistsPermissionLevel ...................................................... 28
3.3.1.2.3 Void FindGroupToDeleteToCreate ............................................................. 29
3.3.1.2.4 Boolean hasCurrentUserAPermissionLevel ................................................ 31
3.3.1.2.5 Boolean isPermissionLevelInRoleAssignment ............................................ 32
3.3.1.3 KeyValList ......................................................................................................... 33
3.3.1.3.1 Bool TryAddKey .......................................................................................... 33
3.3.1.3.2 void CreateKeyValueListNoPrivileges ......................................................... 34
3.3.1.3.3 Void CreateKeyValueList............................................................................. 35
3.3.1.3.4 String GetValueFromKeyNoPrivileges ........................................................ 36
3.3.1.3.5 String GetValueFromKey ............................................................................ 36
3.3.1.3.6 Void SetOrAddValueNoPrivileges ............................................................... 37
3.3.1.3.7 Void SetOrAddValue ................................................................................... 37
3.3.1.4 Lists .................................................................................................................. 37
3.3.1.4.1 Class Field ................................................................................................... 37
3.3.1.4.2 SPListItem CopyItemTo ............................................................................... 38
3.3.1.4.3 SPListItem MoveItemTo ............................................................................. 38
103
3.3.1.4.4 SPList Create ............................................................................................... 38
3.3.1.5 Mailer ............................................................................................................... 41
3.3.1.5.1 Class EmailTemplate ................................................................................... 42
3.3.1.5.2 Void createEmailTemplateList .................................................................... 42
3.3.1.5.3 Void getEmail .............................................................................................. 43
3.3.1.5.4 Void Send .................................................................................................... 44
3.3.1.5.5 Void SendWithAttachments ....................................................................... 46
3.3.1.6 PubManager .................................................................................................... 48
3.3.1.6.1 Struct PageDefinition .................................................................................. 48
3.3.1.6.2 PublishingPage CreatePublishingPage ....................................................... 49
3.3.1.6.3 PageLayout GetPageLayout ........................................................................ 50
3.3.1.6.4 List<PageDefinition> CreatePageDefinitionList .......................................... 50
3.3.1.6.5 List<PublishingPage> CreatePublishingPagesSetWelcome ........................ 51
3.3.1.6.6 List<PublishingPage> CreatePublishingPages ............................................ 53
3.3.1.6.7 Void DeletePublishingPagesSetWelcome .................................................. 53
3.3.1.6.8 Void DeletePublishingPages ....................................................................... 54
3.3.2 Classi accessorie ................................................................................................... 55
3.3.2.1.1 Logging ........................................................................................................ 55
3.3.2.1.1.1 Class Logger ......................................................................................... 55
3.3.2.1.1.2 Class LogExceptions ............................................................................. 60
3.3.2.1.2 Security ....................................................................................................... 61
3.3.2.1.2.1 Class Permissions ................................................................................. 63
3.3.2.1.2.2 Class EncodeDecode ............................................................................ 64
3.4 Feature BlockUsers ....................................................................................................... 67
3.4.1 BlockedUsers/Elements.xml ................................................................................. 67
104
3.4.2 BlockUsers ............................................................................................................ 68
4 Implementazione del framework ........................................................................................ 69
4.1 Esempio di progetto ..................................................................................................... 69
4.1.1 Scopo .................................................................................................................... 69
4.1.2 Ruoli nel sistema ................................................................................................... 69
4.1.3 Fasi del processo ................................................................................................... 71
4.1.4 Requisiti funzionali ............................................................................................... 73
4.1.4.1 Ruoli ed autorizzazioni di processo ................................................................. 73
4.1.4.2 Permessi e funzionalità per attore .................................................................. 73
4.1.4.3 Permessi e visibilità per competenza richieste ............................................... 74
4.2 Progettazione del flusso ............................................................................................... 74
4.3 Suddivisione per macrofasi .......................................................................................... 75
4.4 Analisi di sviluppo del progetto .................................................................................... 75
4.4.1 Definizione delle liste ........................................................................................... 76
4.4.1.1 Descrizione via Metodo ................................................................................... 76
4.4.1.2 Descrizione via XML ......................................................................................... 77
4.4.1.3 Caratterizzazione della lista ............................................................................. 77
4.4.2 Definizione dei permessi ...................................................................................... 80
4.4.3 Creazione dell’item ............................................................................................... 81
4.4.4 Gestione del passaggio di fase ............................................................................. 82
4.4.5 Gestione dei passaggio di macrofase ................................................................... 82
4.4.6 Creazione dei gruppi ............................................................................................. 84
4.4.6.1 Generazione dei gruppi ................................................................................... 84
4.4.6.2 Generazione degli utenti e dei legami ............................................................ 85
4.5 Conclusione dell’esempio ............................................................................................ 86
105
5 Sviluppi futuri ....................................................................................................................... 88
6 Conclusioni ........................................................................................................................... 89
7 Ringraziamenti ..................................................................................................................... 91
8 Appendici ............................................................................................................................. 93
8.1 Appendice A – Algoritmi di Crittazione dei dati in .NET ............................................... 93
8.1.1 Algoritmo di Rijndael ............................................................................................ 95
8.1.1.1 Possibile implementazione in C# ..................................................................... 97
8.2 Appendice B – Diagramma di flusso completo del progetto d’esempio ..................... 98
9 Bibliografia ........................................................................................................................... 99
106
9 Indice delle figure
Figura 1 - Task ................................................................................................................................ 9
Figura 2 - Macro Task ..................................................................................................................... 9
Figura 3 - Esempio di Workflow personalizzato .......................................................................... 11
Figura 4 - Rollback in Macrotask .................................................................................................. 14
Figura 5 - Rollback tra task diversi ............................................................................................... 14
Figura 6 - Eliminazione dati con Rollback .................................................................................... 14
Figura 7 - Inibizione di accesso a dati futuri con Rollback ........................................................... 15
Figura 8 - Dati condivisi in macrotask .......................................................................................... 16
Figura 9 - Strutturazione funzionale della library ........................................................................ 20
Figura 10 - Flusso SPList Create ................................................................................................... 22
Figura 11 - Flusso insertFile ......................................................................................................... 24
Figura 12 - Flusso ensureFolders ................................................................................................. 27
Figura 13 - Flusso SPGroupsCreate .............................................................................................. 28
Figura 14 - Flusso FindGroupToDeleteToCreate ......................................................................... 30
Figura 15 - Flusso TryAddKey ....................................................................................................... 33
Figura 16 - Flusso CreateKeyValueListNoPrivileges ..................................................................... 35
Figura 17 - Flusso Create ............................................................................................................. 39
Figura 18 - Flusso Send ................................................................................................................ 45
Figura 19 - Flusso SendWithAttachments ................................................................................... 46
Figura 20 - Flusso CreatePublishingPagesSetWelcome ............................................................... 52
Figura 21 - Flusso OpenLog .......................................................................................................... 57
Figura 22 - Flusso Assign .............................................................................................................. 64
Figura 23 - Flusso BlockUsers ...................................................................................................... 68
Figura 24 - Flusso d'esempio analizzato ...................................................................................... 75
Figura 25 - Organizzazione strutturale della Macrofase 1 .......................................................... 76
Figura 26 - Creazione di una lista in VS2010................................................................................ 77
Figura 27 - Definizione della lista ................................................................................................. 78
Figura 28 - Schema.xml content type .......................................................................................... 78
Figura 29 - Definizione dei campi ................................................................................................ 79
107
Figura 30 - Definizione della view della lista ............................................................................... 80
Figura 31 - Definizione delle query applicate alla lista ................................................................ 80
Figura 32 - Verifica della fase di un campo .................................................................................. 80
Figura 33 - Verifica di stato .......................................................................................................... 81
Figura 34 – Parziale descrizione dell’itemAdding di nuova richiesta .......................................... 81
Figura 35 - Invio mail e chiusura pratica ...................................................................................... 82
Figura 36 - Generazione nuovi permessi ..................................................................................... 83
Figura 37 – Creazione dell'item (descrizione parziale) ................................................................ 83
Figura 38 - Popolamento dei campi di interesse ......................................................................... 84
Figura 39 - Verifica dei gruppi presenti ....................................................................................... 85
Figura 40 - Creazione dei gruppi .................................................................................................. 85
Figura 41 - Creazione dell'utenza in AD ....................................................................................... 86
Figura 42 - Inserimento di un'utenza di esempio in un gruppo .................................................. 86
Figura 43 - Rijndael SubBytes ...................................................................................................... 95
Figura 44 - Rijndael ShiftRows ..................................................................................................... 96
Figura 45 - Rijndael MixColumns ................................................................................................. 96
Figura 46 - Rijndael AddRoundKey .............................................................................................. 96