• Non ci sono risultati.

Catalogo Swiss Mooc Service

N/A
N/A
Protected

Academic year: 2021

Condividi "Catalogo Swiss Mooc Service"

Copied!
84
0
0

Testo completo

(1)

Studente/i

Tommaso Agnola

Relatore

Riccardo Mazza

Correlatore

Andrea Baldassari

Committente

SUPSI

Corso di laurea

Ingegneria Informatica

Modulo

M00009

Anno

2018/2019

Data

(2)
(3)

Indice

Abstract 1 Introduzione 3 1 Motivazione e Contesto 5 1.1 Motivazione . . . 5 1.2 Contesto . . . 5 1.2.1 edX . . . 5 1.2.2 Open edX . . . 6 1.2.2.1 LMS . . . 7 1.2.2.2 Studio . . . 7 1.2.2.3 Discovery . . . 7

1.2.3 Open edX Devstack . . . 8

2 Tecnologie utilizzate 9 2.1 Tecnologie utilizzate per il back-end . . . 9

2.1.1 Spring, Spring MVC, Spring Data e Spring Boot . . . 9

2.1.2 MySQL . . . 9

2.1.3 Docker . . . 9

2.2 Tecnologie utilizzate per il front-end . . . 10

2.2.1 React . . . 10

2.2.2 Redux . . . 11

2.3 Tecnologie utilizzate per la sicurezza . . . 14

2.3.1 Token JWT . . . 14

2.3.2 Oauth e OAuth 2.0 . . . 15

3 Implementazione 17 3.1 Back-end . . . 17

3.1.1 Utilizzo della piattaforma edX . . . 17

3.1.2 Configurazione . . . 20

(4)

ii INDICE

3.1.4 Database . . . 24

3.1.5 Classi del modello . . . 26

3.1.6 Endpoint REST . . . 29

3.1.6.1 Immagini . . . 29

3.1.6.1.1 Recupero di un’immagine . . . 29

3.1.6.2 Categorie e Sottocategorie . . . 30

3.1.6.2.1 Recupero delle Categorie . . . 30

3.1.6.2.2 Aggiunta di una Categoria . . . 30

3.1.6.2.3 Modifica di una Categoria . . . 31

3.1.6.2.4 Rimozione di una Categoria . . . 32

3.1.6.2.5 Recupero delle Sottocategorie . . . 33

3.1.6.2.6 Aggiunta di una Sottocategoria . . . 33

3.1.6.2.7 Modifica di una Sottocategoria . . . 34

3.1.6.2.8 Rimozione di una Sottocategoria . . . 35

3.1.6.3 Courserun . . . 35

3.1.6.3.1 Recupero dei Courserun . . . 36

3.1.6.3.2 Modifica di un Courserun . . . 36

3.1.6.4 Contenuto della pagina principale . . . 38

3.1.6.4.1 Recupero dell’introduzione . . . 38

3.1.6.4.2 Modifica dell’introduzione . . . 38

3.1.6.4.3 Recupero delle features . . . 39

3.1.6.4.4 Modifica delle features . . . 39

3.1.6.4.5 Recupero delle citazioni . . . 39

3.1.6.4.6 Aggiunta di una citazione . . . 40

3.1.6.4.7 Modifica di una citazione . . . 40

3.1.6.4.8 Rimozione di una citazione . . . 41

3.1.6.4.9 Recupero dei partners . . . 42

3.1.6.4.10 Aggiunta di un partner . . . 42

3.1.6.4.11 Modifica di un partner . . . 43

3.1.6.4.12 Rimozione di un partner . . . 43

3.1.6.5 Organizzazioni . . . 44

3.1.6.5.1 Recupero delle organizzazioni . . . 44

3.1.6.5.2 Modifica dell’immagine di un’organizzazione . . . 45

3.1.6.6 Utenti . . . 45

3.1.6.6.1 Recupero degli utenti . . . 46

3.1.6.6.2 Modifica del ruolo di un utente . . . 46

3.1.6.6.3 Recupero delle informazioni personali . . . 47

3.2 Front-end . . . 49

(5)

3.2.2 Interfaccia e Funzionalità . . . 55

3.2.2.1 Homepage . . . 55

3.2.2.2 Discovery dei Corsi . . . 57

3.2.2.3 Login e Logout . . . 59

3.2.2.4 Sezioni riservate all’amministratore globale . . . 60

3.3 Utenti . . . 64 3.4 Sicurezza . . . 66 4 Piano di Lavoro 69 5 Conclusioni 73 5.1 Problemi Noti . . . 73 5.2 Sviluppi Futuri . . . 73

(6)
(7)

Elenco delle figure

1.1 Logo di edX . . . 6

1.2 Struttura di Open edX . . . 6

2.1 Esempio di componente in React con JSX . . . 10

2.2 Esempio di State . . . 11

2.3 Esempio di Action . . . 12

2.4 Esempio di Reducer . . . 12

2.5 Esempio di Action Creator . . . 12

2.6 Esempio di invocazione di Dispatch . . . 13

2.7 Flusso di un’Action in Redux . . . 13

2.8 Esempio di Token JWT . . . 14

2.9 Logo di Oauth . . . 15

2.10 Funzionamento di Oauth . . . 16

3.1 Struttura del file application.yaml . . . 20

3.2 Workflow dello Scheduler . . . 23

3.3 Diagramma Entity Relationship del Database (1/3) . . . 24

3.4 Diagramma Entity Relationship del Database (2/3) . . . 25

3.5 Diagramma Entity Relationship del Database (3/3) . . . 25

3.6 Schema delle classi riguardanti i corsi . . . 26

3.7 Schema della classe User . . . 27

3.8 Schema delle classi riguardanti la pagina iniziale e le immagini . . . 28

3.9 Tabella riassuntiva degli endpoint . . . 48

3.10 Homepage - Introduzione . . . 55

3.11 Homepage - Features . . . 55

3.12 Homepage - Citazioni . . . 56

3.13 Homepage - Partners . . . 56

3.14 Discovery . . . 57

3.15 Filtri del discovery . . . 57

3.16 Visualizzazione dei corsi filtrati . . . 58

(8)

vi ELENCO DELLE FIGURE

3.18 Pagina di comparazione dei corsi selezionati . . . 59

3.19 Schermata di Login . . . 59

3.20 Schermata di Logout . . . 60

3.21 Modifica dell’introduzione . . . 60

3.22 Gestione delle citazioni . . . 61

3.23 Gestione di un corso . . . 61

3.24 Pagina di Amministrazione - Sezione Users . . . 62

3.25 Pagina di Amministrazione - Sezione Partners . . . 62

3.26 Pagina di Amministrazione - Sezione Categories . . . 63

3.27 Pagina di Amministrazione - Sezione Deafult Images . . . 63

3.28 Tabella riassuntiva dei permessi degli Utenti . . . 65

(9)

Abstract

Lo scopo del progetto è quello di realizzare un portale web dove gli studenti, provenienti da varie università svizzere, possono accedere e consultare corsi organizzati dalle università. Le informazioni sui corsi sono recuperate dai servizi offerti da open edX, una piattaforma mediante cui è possibile creare corsi di vario genere, ampliamente personalizzabili.

Questo strumento funge inoltre da supporto alla piattaforma open edX, dove i corsi risiedo-no e possorisiedo-no essere seguiti.

Oltre alla funzionalità principale di catalogo è richiesta la creazione di una pagina di intro-duzione, dove gli studenti possono informarsi sulle caratteristiche e finalità di Swiss Mooc Service, una sezione dove i responsabili delle università possono modificare alcune infor-mazioni sui corsi come categorie e sottocategorie ed infine una parte di gestione del sito, rivolta all’amministratore globale, dove egli può modificare vari aspetti grafici e di gestione dei permessi.

(10)
(11)

Introduzione

Questo documento rappresenta la documentazione del progetto di diploma dello studente Agnola Tommaso ed è stato redatto con l’intento di comprendere quanto è stato realizzato. Fine non ultimo è anche quello di facilitare la comprensione del codice annesso ad un pos-sibile futuro utilizzatore, guidandolo nelle fasi di sviluppo, nei problemi affrontati, nelle scelte e nei risultati ottenuti.

Seguendo le necessità della piattaforma e le specifiche suggerite dal relatore, è stata ri-chiesta la realizzazione di una portale web suddiviso in varie sezioni e offrente diverse funzionalità, esposte di seguito.

E’ opportuno esporre le informazioni e finalità di Swiss Mooc Service in una pagina dedica-ta, in quanto essi sono concetti fondamentali per comprendere le caratteristiche del portale stesso. In questa pagina devono essere poi presenti alcune citazioni ottenute da SMS, con relativo autore e link al sito dove tale commento è presente. In aggiunta deve essere vi-sibile una lista dei partner che contribuiscono al servizio Swiss Mooc. Come richiesto dal committente, il contenuto di tale pagina deve essere totalmente personalizzabile dall’ammi-nistratore del sito, non necessitante di conoscenze informatiche.

E’ necessario fornire all’utente la possibilità di accedere al sito mediante login in modo tale da identificare le autorizzazioni ad esso concesse. E’ opportuno distinguere un utente am-ministratore, in grado di modificare gli aspetti del sito e le informazioni sui corsi, un utente amministratore di una singola università, in grado di modificare le caratteristiche di un corso offerto dalla suddetta università ed infine un utente senza privilegi.

Aspetto fondamentale del portale sono i corsi a cui gli studenti possono prendere parte. Le informazioni dei corsi vengono recuperate dal servizio di discovery di open edX ma si è deci-so di estenderle aggiungendo delle caratteristiche come richiesto dal relatore. Un requisito è infatti quello di poter raggruppare i corsi aventi gli stessi argomenti e tematiche median-te specifiche camedian-tegorie e sottocamedian-tegorie, gestibili dall’amministratore. Questo aspetto può quindi facilitare la ricerca e la scoperta di nuovi corsi da parte degli studenti. A tal fine sono stati aggiunti al corso dei campi utili a salvare categoria e sottocategoria ad esso associata. E’ inoltre richiesta l’aggiunta di un commento, inserito dall’amministratore, che può fungere da supporto nella consultazione delle informazioni del corso. Le tre informazioni sopre

(12)

ci-4 Introduzione

tate devono poter essere modificabili dall’amministratore globale o da quello dell’università organizzante il corso.

In un’altra pagina è opportuno fornire all’utente una panoramica dei corsi presenti nel siste-ma. Devono essere visualizzate solo alcune delle informazioni relative ai corsi in quanto per leggerne il dettaglio è necessario accedere ad un altra sezione dove le caratteristiche sono esposte con chiarezza. In questa pagina deve essere possibile cercare un corso in base al titolo ed applicare dei filtri di ricerca. Tale funzionalità è richiesta per facilitare e velocizzare l’accesso ad un corso.

E’ infine richiesto di aggiungere la possibilità di comparare più corsi, confrontandone le ca-ratteristiche.

Per soddisfare tali requisiti sono stati sviluppati un applicativo back-end ed uno front-end. Nell’applicativo back-end, realizzato con il supporto di Spring, è stato configurato l’interfac-ciamento con un database che si occupa di immagazzinare i dati; sono stati poi configurati gli endpoint che il front-end utilizzerà per recuperare le informazioni richieste e attuare le opportune modifiche ai dati; è stata quindi predisposta una procedura periodica di aggior-namento dei dati sui corsi presenti nel sistema, interrogando ad intervalli regolari il servizio di discovery di edX.

Nell’applicativo front-end, realizzato con il supporto di React e Redux, sono state create le pagine ed i componenti in grado di interfacciarsi con il back-end e necessari ad offrire le funzionalità sopra descritte.

In entrambi gli applicativi è stato necessario configurare gli aspetti di sicurezza richiesti. Op-portuni end-point sono stati protetti mediante token JWT ed è stato reso disponibile, come richiesto dal committente, l’accesso mediante Google, Facebook o un servizio di login di Swiss Mooc Service, seguendo i dettami del protocollo OAuth 2.0.

(13)

Capitolo 1

Motivazione e Contesto

1.1

Motivazione

Questo progetto è stato realizzato come tesi di Bachelor per il corso di laurea in Ingegneria Informatica svolto alla Scuola Universitaria della Svizzera Italiana (SUPSI) presso il Dipar-timento di Tecnologie Innovative (DTI) situato a Manno. Al termine del percorso formativo si è chiamati a svolgere un progetto della durata di 8/10 settimane. Tale progetto ha come fine quello di applicare le conoscenze e le tecniche apprese durate l’arco della formazione, nonché di dimostrare di essere in grado di documentare e difendere il proprio lavoro davanti ad una commissione di docenti ed esperti del settore.

1.2

Contesto

Swiss Mooc Service (https://www.swissmooc.ch) è una piattaforma svizzera basata su open edX (https://open.edx.org) che offre la possibilità alle università svizzere di eroga-re corsi on-line in stile MOOC1. Il software viene gestito da EPFL che eroga il servizio per varie università, fra cui la SUPSI (https://mooc.supsi.ch). Ogni università che partecipa a questa piattaforma ha un suo portale di corsi e gestisce i propri corsi in maniera indipen-dente dalle altre, nonostante il servizio open edX sia unico.

SUPSI ha ricevuto l’incarico di implementare il catalogo di questa piattaforma, che funga

da vetrina di presentazione dei corsi offerti da tutte le università svizzere.

1.2.1

edX

edX[1] è una piattaforma legata all’istruzione fondata dall’università di Harzard e da MIT. E’ un servizio open source e senza scopo di lucro che permette ad università ed aziende

1

(14)

6 Motivazione e Contesto

di offrire corsi in stile MOOC, ampiamente personalizzabili, accessibili ai propri studenti o collaboratori.

Figura 1.1: Logo di edX

1.2.2

Open edX

Open edX[2] è la piattaforma dove risiedono e vengono gestiti i corsi di edX. Essa è suddivi-sa in varie parti, ognuna con funzionalità specifiche; di seguito sono esposte quelle utilizzate nel prgetto.

(15)

Ogni organizzazione che necessita Open edX ha la possibilità di installarne un’istanza locale in modo tale da gestire in sicurezza le proprie informazioni, utilizzando gli strumenti offerti da edX.

Una delle caratteristiche principali di questa piattaforma è la distinzione tra corso e course run. Un course run è di fatto una specifica sessione di un determinato corso. Un corso è una collezionie di course run, accomunati dalle stesse tematiche ma strutturati ed organizzati in maniera diversa.

1.2.2.1 LMS

LMS2è uno strumento multipiattaforma utilizzato da studenti e collaboratori.

Grazie ad esso gli istruttori possono configurare nuovi corsi, comunicare con gli studenti iscritti ad essi, gestire i voti ad altro ancora.

Gli studenti possono invece gestire il proprio profilo, incluse le iscrizioni ai vari corsi e con-sultare i corsi offerti dalla propria università.

Vi è inoltre una sezione dedicata ai forum con i quali gli studenti possono comunicare con gli istruttori e viceversa.

1.2.2.2 Studio

Studio consente agli istruttori di creare i contenuti di un determinato corso, configurandone i course runs e le lezioni in essi presenti.

Tramite esso è possibile gestire le informazioni principali dei corsi ed è di fatto lo strumento di riferimento dei professori.

Consente inoltre, mediante lo standard XML, di importarte ed esportare i corsi configurati.

1.2.2.3 Discovery

Discovery[3] è uno strumento con il quale è possibile recuperare le informazioni provenienti dai servizi Studio e LMS. E’ utilizzato anche da applicativi esterni per accedere ai dati di una specifica installazione di Open edX.

Discovery utilizza Elasticsearch3 per indicizzare e recuperare i dati relativi a corsi e course run.

Può essere interrogato opportunamente per ottenere le informazioni necessarie all’applica-tivo che ne richiede l’utilizzo.

2Learning Management System 3

(16)

8 Motivazione e Contesto

1.2.3

Open edX Devstack

Devstack è uno strumento sviluppato da OpenStack per gestire e facilitare l’installazio-ne di interi sistemi o una porziol’installazio-ne di essi al fil’installazio-ne di sperimentarl’installazio-ne le funzionalità. Open edX Devstack[4] è un’istanza di Devstack che permette l’installazione locale di Open edX attraverso un insieme di contenitori Docker, comunicanti fra loro.

(17)

Capitolo 2

Tecnologie utilizzate

2.1

Tecnologie utilizzate per il back-end

2.1.1

Spring, Spring MVC, Spring Data e Spring Boot

Spring[5] è un framework che consente di sviluppare applicazioni complesse su piattaforma

Java. Fornisce diverse funzionalità, come dependency injection, supporto per JPA e JDBC e molti altri.

Sfruttando le funzionalità offerte da Spring, Spring MVC permette di realizzare applicazioni basate sul pattern MVC in modo semplice ed automatico. Spring Boot permette di semplifi-care e velocizzare la configurazione e lo sviluppo di un’applicazione Spring.

Spring Data fornisce un set di API, grazie alle librerie JPA e Hibernate, per gestire l’accesso ai dati indipendente dal tipo di DBMS utilizzato in modo facile ed immediato.

2.1.2

MySQL

MySQL[6] è un Database Management System (DBMS) di tipo relazionale. Si occupa di

interagire con il database per persistere, gestire e recuperare i dati.

2.1.3

Docker

Docker[7] è un tool che permette di creare ed eseguire applicazioni all’interno di container.

Un container è un’unità di software che contiene il codice e le dipendenze necessarie per eseguire un’applicazione.

Docker si differenzia da una macchina virtuale perché non crea un intero sistema operativo, ma utilizza lo stesso kernel Linux sul quale è in esecuzione per eseguire le applicazioni. In questo modo si ottiene un consistente boost delle performance e riduce le dimensioni del-l’applicazione rispetto alla virtualizzazione. Un container include tutto ciò di cui ha bisogno l’applicazione per eseguire che non è presente sulla macchina in cui viene avviata.

(18)

10 Tecnologie utilizzate

applicazione, perché lo sviluppatore non deve preoccuparsi della configurazione dell’am-biente di runtime. Inoltre, aumenta la portabilità, perché lo stesso applicativo può venire eseguito alla stessa maniera su qualsiasi macchina che supporta Docker, consente di iso-lare le applicazioni dalle risorse e di separare completamente i vari container, impedendo dall’esterno di visualizzare quali processi vengono eseguiti all’interno di un container.

2.2

Tecnologie utilizzate per il front-end

2.2.1

React

React[8, 9]1 è una libreria JavaScript utilizzata per creare interfacce utente complesse. È stata creata ed è mantenuta da Facebook e da un’ampia comunità di sviluppatori.

Per la creazione dell’interfaccia vengono utilizzati i linguaggi HTML, CSS e JavaScript. HTML permette di definire la struttura della pagina, CSS il suo stile e JavaScript permet-te di implementarne la logica.

In React il linguaggio HTML viene utilizzato per creare "componenti Web" iniettabili e riuti-lizzabili in altre pagine.

Sfruttando i componenti, il numero di pagine è ridotto al minimo. Si preferisce quindi alterare la visibilità dei componenti piuttosto che predisporre più pagine per la visualizzazione dello stesso contenuto.

Le applicazioni, caratterizzate da una sola pagina, che utilizzano i componenti per comporre l’interfaccia utente prendono il nome di Single Page Applications (SPA).

La React, come definito nella documentazione ufficiale, suggerisce di usare JSX[10, 11] per lo sviluppo delle applicazioni web.

JSX (JavaScript eXtension) è un’estensione sintattica di Javascript che permette di scrivere la struttura dei vari componenti usando una sintassi simile al linguaggio HTML.

Figura 2.1: Esempio di componente in React con JSX

1

(19)

Con i componenti di React è possibile inserire il codice di markup e la logica nello stesso file, separandone le responsabilità. In questo modo i componenti inseriti in una pagina sono debolmente accoppiati alla pagina stessa. Mediante gli Styled-Component(https: //www.styled-components.com/) è possibile definire nello stesso file anche lo stile con cui il componente viene presentato.

2.2.2

Redux

Redux[12, 13] è una libreria utilizzabile in React per gestire lo stato di un’applicazione. Il suo utilizzo rende prevedibile i cambi di stato dell’intera applicazione, limitandone i valori assumibili e i momenti in cui esso può cambiare.

L’applicazione è caratterizzata da un unico stato, dettostate e rappresentato mediante un

oggetto JSON, situato in unostore.

Invocando specifiche funzioni pure dettereducer, alle quali bisogna specificare un’azione

da compiere, dettaaction, è possibile mutare lo stato.

Redux è legato a tre principi fondamentali:

Single source of truth: l’interfaccia grafica e le funzionalità si devono basare

princi-palmente sulle informazioni presenti nello stato.

State is read-only: è possibile soltanto leggere lo stato mentre la modifica è affidata

ad actions e reducers.

Changes are made with pure functions: le mutazioni dello stato devono avvenire

solo mediante funzioni pure. Esse sono funzioni che producono lo stesso output dato lo stesso input e non comportano effetti collaterali.

Redux si basa su 4 concetti già accennati:

State: è lo stato dell’applicazioni. Contiene le informazioni che la caratterizzano.

Solitamente è un oggetto con struttura ad albero.

(20)

12 Tecnologie utilizzate

Store: è la parte di Redux necessaria per mantenere lo stato dell’applicazione. È

di fatto un contenitore che consente l’accesso allo stato e permette di mutarlo. E’ necessario configurarlo per poter utilizzare Redux.

Action: è un oggetto JavaScript che rappresenta l’azione da invocare se si vuole

cam-biare lo stato dell’applicazione. Essa è caratterizzata da una proprietà type che iden-tifica il tipo di azione che si intende eseguire ed una proprietà payload che contiene eventuali parametri utili a modificare opportunamente lo stato.

Figura 2.3: Esempio di Action

Reducer: è una funzione JavaScript che prende in input lo stato corrente e l’azione

da eseguire e restituisce lo stato successivo. Sfrutta le proprietà dell’azione per indivi-duare le operazioni necessarie a cambiare opportunamente lo stato. Come anticipato, questa funzione deve essere pura.

Figura 2.4: Esempio di Reducer

Nel progetto sono inoltre utilizzati i concetti di:

Action creator: è una funzione Javscript che genera un’azione in base a determinati

parametri. Questo permette di evitare di passare ai reducers azioni che essi non possono riconoscere o strutturate in maniera errata.

(21)

Dispatcher: è un componente che ha il compito di inviare un’azione allo store,

proce-dendo così alla mutazione dello stato.

Figura 2.6: Esempio di invocazione di Dispatch

Il flusso generale per modificare lo stato corrente di un’applicazione segue i seguenti passi:

1. Viene individuata una Action, eventualmente generata tramite un Action creator.

2. Tale Action viene inviata allo Store tramite un Dispatcher.

3. All’interno dello Store, un Reducer sostituisce allo stato corrente l’eventuale nuovo stato individuato in base all’analisi della Action.

(22)

14 Tecnologie utilizzate

2.3

Tecnologie utilizzate per la sicurezza

2.3.1

Token JWT

JSON Web Token (JWT)[14, 15] è uno standard aperto (RFC 7519) che definisce un modo compatto e autonomo per trasmettere informazioni in modo sicuro tra parti tramite oggetti JSON. Queste informazioni possono essere verificate perché firmate digitalmente. I Token JWT possono essere firmati mediante chiave segreta o pubblica.

Un Token JWT è formato da 3 parti separate da un punto:

Header: diviso in tipo di token e tipologia di algoritmo di firma utilizzato.

{

" a l g ": " HS256 " ,

" t y p ": "JWT" }

Payload: contiene i claims. I Claim sono dichiarazioni relative ad un’entità composte

da chiave e valore.

{

" sub ": "1234567890" ,

" name ": " John Doe " ,

" admin ": t r u e }

Signature: usata per verificare che il messaggio non è stato cambiato e nel caso di

token firmati con una chiave privata, verifica che il mittente è chi dice di essere.

Di seguito si può vedere un esempio di token con l’header e il payload mostrati sopra e cifrato con una chiave segreta:

(23)

2.3.2

Oauth e OAuth 2.0

Figura 2.9: Logo di Oauth

OAuth[16] è un protocollo di rete che consente ad un determinato client l’accesso a risorse specifiche presenti su un server a seguito dell’approvazione dell’utente proprietario. Il tutto è realizzato mediante il supporto di un token fornito da un server autorizzativo.

Questo protocollo è utilizzato da Google, Amazon, Facebook e Twitter per permettere all’u-tente di condividere le proprie informazioni (come username o mail) in maniera sicura ad altre applicazioni o siti web, senza che gli utenti siano costretti a registrarsi a tale sito. E’ inoltre garantito che la password di accesso non venga condivisa ad alcun client.

Per gli sviluppatori di applicazioni è un metodo per interagire con dati protetti senza dover gestire un’autenticazione propria alla suddetta applicazione. OAuth garantisce mediante i service provider l’accesso da parte di terzi ai dati degli utenti proteggendo al tempo stes-so le loro credenziali. Permette in pratica ad un utente di dare accesstes-so alle informazioni presenti su un sito, detto service provider, ad un altro sito, chiamato consumer, in maniera totalmente sicura e consapevole.

OAuth 2.0 è un’evoluzione del precedente.

E’ stata aggiunta la possibilità di prolungare la scadenza del token di accesso fornito dal server autorizzativo, se richiesto.

Vi è inoltre l’aggiunta di un server mediatore avente come principale compito quello di ge-stire i token di accesso tra client e server. Questo server può essere lo stesso che ospita le risorse alle quali accedere.

Il suo funzionamento[17] può essere descritto come segue:

1. L’applicazione richiede all’utente l’autorizzazione ad accedere alle risorse del servi-zio. L’applicazione deve fornire il client ID, il client secret, l’URI a cui il client ver-rà reindirizzato successivamente al login avvenuto e gli scopi per i quali i dati sono richiesti.

(24)

16 Tecnologie utilizzate

3. L’applicazione richiede un token di accesso al server di autorizzazione presentando la propria identità e l’authorization grant.

4. Se l’identità dell’applicazione è autenticata e authorization grant valido, il server di autorizzazione emette il token di accesso. L’autorizzazione è quindi completa.

5. L’applicazione richiede la risorsa al server e presenta il token di accesso per l’autenti-cazione.

6. Se il token di accesso è valido, il server ritorna la risorsa all’applicazione

(25)

Capitolo 3

Implementazione

3.1

Back-end

Il server è stato sviluppato con il framework Spring Boot.

Esso si interfaccia con la piattaforma Open edX per recuperare le informazioni da offrire agli utilizzatori. Tali informazioni sono immagazzinate mediante opportune classi in un databa-se, con una struttura specifica, e messe a disposizione mediante determinati endpoint. Il recupero delle informazioni avviene in maniera periodica tramite uno Scheduler.

Ciascuna delle funzionalità sopra citate verrà esposta nelle prossime sezioni.

3.1.1

Utilizzo della piattaforma edX

Una delle principali difficoltà incontrate durante la realizzazione di questo progetto è stata interfacciarsi con i servizi esterni offerti da edX per recuperare le informazione sui corsi offerti dalla piattaforma.

E’ stata dapprima configurata un’istanza locale di edX tramite Devstack. Sono stati quindi installati un gruppo di container docker, comunicanti tra loro con il fine di fornire accesso alla piattaforma con dati locali, utilizzabile come ambiente di test. Sono stati poi inseriti dei corsi di prova e configurati diversi utenti. Per vari problemi legati ai certificati di sicurezza non è stato possibile continuare ad utilizzare l’istanza locale. Contattando i responsabili di Swiss Mooc Service, l’applicazione è stata configurata per poter comunicare con l’istanza pubblica, accessibile mediante specifici url.

I due principali servizi con i quali è stato necessario interfacciarsi sono:

LMS: Necessario per autenticare l’applicazione. Fornendo i dati opportuni nel body di

una richiesta POST, tale servizio ritorna un token di accesso utilizzabile nelle richieste al discovery.

L’endpoint da interrogare è il seguente:

(26)

18 Implementazione

Nel corpo della richiesta è necessario specificare il tipo di concessione che deve for-nire l’LMS, client_id e client_secret che identificano l’applicazione. Questi ultimi dati sono stati forniti dai responsabili della piattaforma edX. I campi inseriti nel body sono i seguenti:

client_id 5fe78feeecc30729847e

client_secret 5588cb5f547a780fab4afae822f7cf064f25156c

grant_type client_credentials

La risposta del servizio è strutturata come segue:

{ " access_token ": ACCESS_TOKEN, " i d _ t o k e n ": ID_TOKEN , " e x p i r e s _ i n ": 2591999 , " t o k e n _ t y p e ": " Bearer " , " scope ": " p r o f i l e openid e m a i l p e r m i s s i o n s " }

Da tale risposta è necessario considerare il valore di access_token, da specificare nell’header delle richieste al Discovery.

Discovery: Necessario per recuperare le informazioni sui corsi presenti nella

piatta-forma. Fornendo il token, recuperato in precedenza, nell’header di una richiesta GET, tale servizio ritorna i dati richiesti.

L’endpoint da interrogare è il seguente:

GET https://discovery.test-swissmooc.ch/api/v1/courses/

L’header della richiesta deve essere così strutturato:

Authorization Bearer ACCESS_TOKEN

Un esempio di risposta del servizio è strutturata come segue:

{

" co unt ": 33 ,

" n e x t ": " h t t p s : / / d i s c o v e r y . t e s t−swissmooc . ch / a p i / v1 / courses / ? l i m i t =20& o f f s e t = 2 0 " ,

" p r e v i o u s ": n u l l , " r e s u l t s ": [ { " key ": "CSM+ 0 1 " , " u u i d ": " 6 df0bc32−fedc−4c5d−820a−39b609abfb56 " , " t i t l e ": " UNIGE D e mo n s tr a ti o n Course " , " course_runs ": [ { " key ": " course−v1 :CSM+01+201901" , " u u i d ": " bf91635f −9420−4678−98bb−90782420d8f4 " , " t i t l e ": "CSM D e mo n s tr a ti o n Course " , " image ": n u l l , " s h o r t _ d e s c r i p t i o n ": n u l l , " m a r k e t i n g _ u r l ": " course / csm−d e m o n s t r a t i o n−course . . . " , " s e a t s ": [ ] , " s t a r t ": "2019−01−01T00 : 0 0 : 0 0 Z " , " end ": "2020−01−01T00 : 0 0 : 0 0 Z " , " e n r o l l m e n t _ s t a r t ": "2019−01−01T00 : 0 0 : 0 0 Z " , " e n r o l l m e n t _ e n d ": "2020−01−01T00 : 0 0 : 0 0 Z " ,

(27)

" p a c i n g _ t y p e ": " i n s t r u c t o r _ p a c e d " , " t y p e ": n u l l , " s t a t u s ": " p u b l i s h e d " , " course ": "CSM+ 0 1 " , " f u l l _ d e s c r i p t i o n ": n u l l , " announcement ": n u l l , " v i d e o ": n u l l , " c o n t e n t _ l a n g u a g e ": n u l l , " l i c e n s e ": " " , " outcome ": n u l l , " t r a n s c r i p t _ l a n g u a g e s ": [ ] , " i n s t r u c t o r s ": [ ] , " s t a f f ": [ ] , " m i n _ e f f o r t ": n u l l , " m a x _ e f f o r t ": n u l l , " weeks_to_complete ": n u l l , " m o d i f i e d ": "2019−08−19T00 : 2 4 : 2 5 . 3 7 7 7 8 1 Z " , " l e v e l _ t y p e ": n u l l , " a v a i l a b i l i t y ": " C u r r e n t " , " m o b i l e _ a v a i l a b l e ": f a l s e , " hidden ": f a l s e , " r e p o r t i n g _ t y p e ": " mooc " , " e l i g i b l e _ f o r _ f i n a n c i a l _ a i d ": t r u e , " f i r s t _ e n r o l l a b l e _ p a i d _ s e a t _ p r i c e ": n u l l , " h a s _ o f a c _ r e s t r i c t i o n s ": f a l s e , " e n r o l l m e n t _ c o u n t ": 0 , " r e c e n t _ e n r o l l m e n t _ c o u n t ": 0 } , { } ] , " e n t i t l e m e n t s ": [ ] , " owners ": [ { " u u i d ": "94 f67628−b448−4913−8e2c−8541c1c13cdb " , " key ": "CSM" , " name ": "CSM" , " c e r t i f i c a t e _ l o g o _ i m a g e _ u r l ": " h t t p s : / / os . u n i l . c l o u d . s w i t c h . ch / . . . / SMS−l o g o . png " , " d e s c r i p t i o n ": n u l l , " homepage_url ": n u l l , " t a g s ": [ ] , " l o g o _ i m a g e _ u r l ": " h t t p s : / / os . u n i l . c l o u d . s w i t c h . ch / . . . / SMS−l o g o . png " , " m a r k e t i n g _ u r l ": n u l l } ] , " image ": n u l l , " s h o r t _ d e s c r i p t i o n ": n u l l , " f u l l _ d e s c r i p t i o n ": n u l l , " l e v e l _ t y p e ": n u l l , " s u b j e c t s ": [ ] , " p r e r e q u i s i t e s ": [ ] , " p r e r e q u i s i t e s _ r a w ": n u l l , " e x p e c t e d _ l e a r n i n g _ i t e m s ": [ ] , " v i d e o ": n u l l , " sponsors ": [ ] , " m o d i f i e d ": "2019−08−07T08 : 4 0 : 1 0 . 8 3 9 7 0 7 Z " , " m a r k e t i n g _ u r l ": n u l l , " s y l l a b u s _ r a w ": n u l l , " outcome ": n u l l , " o r i g i n a l _ i m a g e ": n u l l , " c a r d _ i m a g e _ u r l ": n u l l , " c a n o n i c a l _ c o u r s e _ r u n _ k e y ": " course−v1 :CSM+01+2019" , " e x t r a _ d e s c r i p t i o n ": n u l l , " a d d i t i o n a l _ i n f o r m a t i o n ": n u l l , " f a q ": n u l l , " l e a r n e r _ t e s t i m o n i a l s ": n u l l , " e n r o l l m e n t _ c o u n t ": 0 , " r e c e n t _ e n r o l l m e n t _ c o u n t ": 0 , " t o p i c s ": [ ] , " programs ": [ ] } . . .

Da ogni course_run presente nella risposta vengono estratte alcune informazioni e salvate nel database mediante opportune classi, come spiegato in seguito.

(28)

20 Implementazione

3.1.2

Configurazione

Nel file che prende il nome di application.yaml è possibile modificare le configurazioni del back-end. Tale file assume la seguente struttura:

Figura 3.1: Struttura del file application.yaml

Modificando i valori relativi a spring.datasource è possibile configurare l’accesso al databa-se specificando url, udataba-sername e password.

Nella sezione riguardante la sicurezza via oauth2 relativa a spring (spring.security.oauth2) è possibile configurare i dati dei provider che possono garantire l’accesso tramite oauth2. Per garantire la possibilità di accedere tramite i provider Google e Facebook è stato necessario ottenere i dati di configurazione delle suddette applicazioni. Nello specifico è stato neces-sario configurare una nuova applicazione Facebook mediante il linkhttps://developers. facebook.com/apps e Google mediante il link https://console.developers.google. com/. Una volta fatto ciò è stato possibile recuperare i dati relativi a clientId, clientSecret e scope da inserire nel file di configurazione.

I suddetti provider sono al momento così configurati:

Google:

{

" web ": {

" c l i e n t _ i d ": "618395890731− b 4 j l 4 3 j m m i q j h c k j 0 h 1 9 5 l v 8 6 8 k o s m e v . apps . g o o g l e u s e r c o n t e n t . com " ,

" p r o j e c t _ i d ": " provaoauth2 −248007",

" a u t h _ u r i ": " h t t p s : / / accounts . google . com / o / oauth2 / auth " ,

" t o k e n _ u r i ": " h t t p s : / / oauth2 . g o o g l e a p i s . com / to ken " ,

" a u t h _ p r o v i d e r _ x 5 0 9 _ c e r t _ u r l ": " h t t p s : / / www. g o o g l e a p i s . com / oauth2 / v1 / c e r t s " ,

" c l i e n t _ s e c r e t ": " j 0 r 9 N i−BdkhfdFPOJipEoOqI " ,

(29)

" h t t p : / / c a t a l o g−be . dyndns24 . ch / o a u t h 2 _ c a l l b a c k / google ", " h t t p : / / l o c a l h o s t : 8 0 8 0 / o a u t h 2 _ c a l l b a c k / google " ] , " j a v a s c r i p t _ o r i g i n s ": [ " h t t p : / / l o c a l h o s t :8080 ", " h t t p : / / c a t a l o g−be . dyndns24 . ch " ] } } • Facebook: ID app 346055012964482

Chiave segreta 32dc572d3d5f7889f44eb989dc7b3289

Nome visualizzato SmsAuthentication

Gli stessi dati relativi all’autenticazione offerta dal servizio SMS sono stati configurati e forniti dal responsabile del progetto SMS. Nello specifico:

Client ID 033f42d17efdd610ddae

Client Secret 3eaf94aae5ea41b0656ad39a6cd8d31bbd2925a9

Redirect URI http://catalog-be.dyndns24.ch/oauth2_callback/sms

Authorisation Request Endpoint /oauth2/authorize

Access Token Endpoint /oauth2/access_token

Username Endpoint /api/user/v1/me

Nella sezione app.auth è possibile configurare la stringa segreta mediante la quale cifrare i token JWT relativi all’autenticazione dell’utente e la loro validità espressa in millisecondi. In app.oauth2.authorizedRedirectUris è possibile specificare la lista degli url abilitati al reindi-rizzamento successivo all’autenticazione mediante oauth2. Nella sezione auth è possibile specificare l’url del servizio di LMS con relativi id, password e tipo di token, da specificare nell’header per ottenere un token di accesso ai servizi. Nella sezione discovery è possibile specificare l’url del servizio di DISCOVERY. Modificando il valore di fetch.time è possibile specificare l’intervallo di tempo espresso in millisecondi tra un’aggiornamento del database e l’altro (comunicando con il discovery). Infine admin.email permette di configurare l’email che deve avere l’amministratore del sito per essere riconosciuto come tale.

(30)

22 Implementazione

3.1.3

Scheduler

Come anticipato, le informazioni relative ai corsi presenti nel sistema sono recuperate dal servizio di discovery della piattaforma edX. Questi dati vengono recuperati e immagazzinati nel database, pronti per essere utilizzati dall’applicativo front-end.

Per mantenere consistenza è necessario eseguire un aggiornamento periodico, interrogan-do nuovamente il servizio di edX e aggiornaninterrogan-do regolarmente i corsi presenti nel database. Tale operazione è resa possibile grazie ad uno Scheduler, realizzato con il supporto di Spring Boot.

La frequenza del suddetto aggiornamento è configurabile, modificando l’attributo fetch.time del file di configurazione del progetto.

Le operazioni svolte, seguendo la frequenza impostata, sono le seguenti:

1. Se il token necessario per effettuare la richiesta al discovery non è presente in me-moria esso viene recuperato interrogando il servizio LMS di edX.

2. Viene eseguita una richiesta GET al servizio di discovery di edX specificando nel-l’header il token precedentemente recuperato.

3. La risposta viene convertita mediante le classi di appoggio situate nel package json-Conversion.

4. Viene creata una lista che conterrà i CourseRun da aggiungere al Database

5. Per ogni corso incluso nella risposta vengono eseguite le seguenti azioni:

(a) Viene creato un’istanza newCourseRun delle classe CourseRun e ad ogni cam-po viene assegnato il relativo valore presente nel corso incluso nella riscam-posta del discovery.

(b) Se nel corso è specificato l’organizzatore, esso viene inserito nel database (se non è già presente) e assegnato al campo organization di newCourseRun. Se nel corso non è specificato nessun organizzatore, al campo organization di new-CourseRun viene assegnato una stringa vuota.

(c) Se nel corso è presente un’immagine ad esso associata, viene aggiunta al data-base (se non è già presente) e al campo imageurl di newCourseRun viene asse-gnato l’url che identifica tale immagine. Se nel corso non è specificata nessuna immagine, al campo imageurl di newCourseRun viene assegnata una stringa vuota.

(d) Se un corso con il medesimo uuid è già presente del database, vengono recu-perati categoria, sottocategoria e nota e vengono assegnati ai relativi campi di newCourseRun.

(31)

6. La tabella contenente i CourseRun viene svuotata e vengono aggiunti i nuovi Course-Run presenti nella lista precedemente creata.

Figura 3.2: Workflow dello Scheduler

Durante la fase di conversione per strutturare la risposta del server attraverso le classi del package jsonConversion è stato scelto di impostare i campi a null qual’ora essi siano vuoti o non riconosciuti. Questa scelta comporta la garanzia di continuità di funzionamento del server anche nel caso in cui la struttura della risposta del discovery cambi in futuro.

E’ stato scelto inoltre di recuperare solamente categoria, sottocategoria e nota dai Course-Run prima che essi siano eliminati dal database in quanto i suddetti 3 campi sono gli unici non presenti nella risposta del discovery e modificabili dal front-end.

(32)

24 Implementazione

3.1.4

Database

Per il salvataggio delle informazioni è stato utilizzato utilizzato MySQL, un DBMS di tipo relazionale associato al server grazie al framework JPA (Java Persistence API).

La struttura del database può essere divisa in 3 parti.

La prima parte comprende le entità che caratterizzano la ricerca dei corsi nel sito. L’entità fondamentale è CourseRun, appartenente ad una determinata Organization e assegnato a una specifica Category e Subcategory.

(33)

La seconda parte comprende l’entità User necessario per gestire l’autenticazione e l’asse-gnazione di particolari ruoli che determinano la possibilità di accesso a determinate parti del sito e la possibilità di compimento di determinate azioni.

Figura 3.4: Diagramma Entity Relationship del Database (2/3)

L’ultima parte è invece un insieme di entità utilizzate per salvare il contenuto della pagina iniziale e renderlo modificabile dall’amministratore del sito, come richiesto dal committente. Vi è inoltre l’entità Image, utilizzata per salvare le varie immagini presenti nel sito e renderle disponibili attraverso specifici url.

(34)

26 Implementazione

3.1.5

Classi del modello

Figura 3.6: Schema delle classi riguardanti i corsi

Le informazioni sui corsi offerti dalle varie organizzazioni vengono recuperate dal servizio di discovery di Swissmooc. Tali informazioni sono strutturate in maniera diversa rispetto alle classi del backend sviluppato nel seguente progetto, quindi vengono convertite e salvate nel database seguendo il modello della classe CourseRun.

Rispetto ai dati recuperati dal servizio di discovery sono stati aggiunti campi per identificare una categoria, una sottocategoria e una nota che caratterizzano il corso. Queste informa-zioni non sono recuperate da altri servizi ma sono assegnate dall’amministratore globale o dall’amministrazione dell’università che offre il corso.

Quando un corso viene inserito per la prima volta nel sistema, category e subcategory han-no valore null mentre han-note stringa vuota.

Le categorie e le sottocategorie sono create e gestite nella sezione Categories della pagina di amministrazione mentre l’assegnazione della categoria/sottocategoria ad un determinato corso avviene nella pagina di dettaglio del corso, come per la modifica della nota riferita ad esso.

Quando ad un corso non è assegnata alcuna immagine, nella pagina in cui si possono ri-cercare e filtrare gli stessi viene visualizzata l’immagine di default dell’organizzazione che offre il corso. Tale immagine può essere modificata dall’amministratore globale del sito nella sezione Default Images della pagina di amministrazione.

(35)

Figura 3.7: Schema della classe User

Durante la fase di login, se le informazioni dell’utente sono già presenti nel sistema vengono aggiornate mentre se non sono presenti queste ultime vengono aggiunte. Tali informazioni sono fornite dal provider che ha da poco gestito l’accesso.

L’autenticazione mediante Google e Facebook permette di recuperare informazioni riguar-danti nome e email dell’utente mentre quella tramite il servizio offerto da Swiss Mooc per-mette di recuperare solo l’username. Per mantenere uniformità tra i vari provider è stato deciso di salvare comunque nome e mail dell’utente, anche se mediante Swiss Mooc non è possibile recuperarle; in quest’ultimo caso il campo mail viene riempito con una stringa che rispecchia la struttura USERNAME@sms.com mentre al posto del nome utente viene immesso l’username. Non è stato possibile lasciare vuoti o nulli questi campi in quando Spring Security non lo permette.

Nel file di configurazione del progetto backend è possibile impostare l’username dell’ammi-nistratore globale. Se in fase di autenticazione il sistema riconosce tale username, all’utente viene assegnato il ruolo di ROLE_ADMIN_SUPER. In caso contrario viene assegnato il ruo-lo ROLE_USER.

Questi ruoli possono essere poi modificati dall’amministratore globale nella sezione Users della pagina di amministrazione del sito. In questa sezione è possibile assegnare ad uno specifico utente i ruoli sopra citati oppure è possibile renderlo amministratore di una spe-cifica organizzazione, assegnandogli il ruolo ROLE_ADMIN_ seguito dal nome dell’orga-nizzazione. In questo modo l’utente sarà in grado di modificare le informazioni (categoria, sottocategoria e nota) dei corsi offerti dalla propria organizzazione.

(36)

28 Implementazione

Figura 3.8: Schema delle classi riguardanti la pagina iniziale e le immagini

Nella pagina principale è possibile analizzare l’introduzione al sito e le caratteristiche di que-st’ultimo, i partner che hanno contribuito alla sua realizzazione e varie citazioni provenienti da diverse fonti. E’ stato necessario realizzare delle classi per gestire tali informazioni in quanto il committente ha richiesto che l’amministratore globale avrebbe dovuto poterle mo-dificare.

Un oggetto MainContent contiene le informazioni visualizzate nella parte superiore della pagina ossia introduzione e features; vi sono poi classi apposite per Partners e citazioni (Press). L’amministratore può modificare, eliminare e aggiungere nuovi partner nella sezio-ne Partsezio-ners della pagina di amministraziosezio-ne mentre può aggiungere, modificare e eliminare le citazioni direttamente nella pagina iniziale.

La classe Image è infine utilizzata per immagazzinare i dati relativi alle immagini per poi essere recuperate dal sito.

(37)

3.1.6

Endpoint REST

Tutti gli endpoints sono accomunati dal fatto che se un utente tenta di effettuare un’opera-zione a lui non concessa, il server ritornerà il seguente errore:

{ " timestamp ": TIMESTAMP, " s t a t u s ": 403 , " e r r o r ": " Forbidden " , " message ": " Forbidden " , " path ": PATH }

In alcuni di essi, per motivi di sicurezza, è necessario fornire il token ottenuto a seguito dell’autenticazione.

3.1.6.1 Immagini

I vari endpoint che seguiranno sono caratterizzati dal fatto che le immagini sono in formato Data URI’s. Le risposte che il server invierà conterranno quindi un link all’immagine invece che l’immagine in formato base64.

Questa convenzione ha permesso di velocizzare la comunicazione con il server e il carica-mento dell’immagine in sè. Utilizzando un url che identifica una risorsa infatti si può sfruttare la cache del browser per velocizzare le operazioni di caricamento.

Tale soluzione è stata implementata anche per mantenere conformità con gli endpoint del-la piattaforma edX in quanto anche anch’essi non ritornano l’intera immagine ma un Url attraverso cui accedervi.

3.1.6.1.1 Recupero di un’immagine

Una volta ottenuto l’Url che la indentifica, l’applicativo recupera l’immagine presente nel database tramite il seguente endpoint:

GET /image/IMAGE_ID

La visione delle immagini deve essere accessibile ad ogni utente quindi non è necessario fornire alcun Authorization Token.

La risposta del server contiene quindi l’immagine originale in formato jpeg, utilizzabile nei vari componenti del front-end.

Se si cerca di recuperare un’immagine non presente nel database, fornendo quindi un iden-tificativo non corrispondente a nessuna risorsa, la risposta del server seguirà la seguente struttura:

{

" timestamp ": TIMESTAMP,

(38)

30 Implementazione

" e r r o r ": " Not Found " ,

" message ": " Image n o t found w i t h i d : IMAGE_ID " ,

" path ": " / image / IMAGE_ID " }

3.1.6.2 Categorie e Sottocategorie

A ogni corso presente nel sistema è possibile assegnare una categoria e una sottocate-goria. Questa operazione può essere compiuta dall’amministratore dell’organizzazione che propone il corso e dall’amministratore globale del sito. Oltre ad assegnare una categoria o una sottocategoria ad uno specifico corso, l’amministratore può creare nuove categorie e nuove sottocategorie, modificarle ed eliminarle. Queste operazioni sono effettuabili nella pagina di amministrazione del sito, navigando nella sezione Categories.

Nella pagina di discovery dei corsi è possibile quindi filtrare la ricerca in base ad una specifica categoria, in modo da semplificare l’utilizzo all’utente.

3.1.6.2.1 Recupero delle Categorie

L’applicativo recupera le categorie salvate nel database tramite il seguente endpoint:

GET /categories

La visione delle categorie deve essere accessibile ad ogni utente quindi non è necessario fornire alcun Authorization Token.

La risposta del server contiene la lista delle categorie presenti nel database, con relativi identificativi: [ { " i d ": CATEGORY_ID, " categoryName ": CATEGORY_NAME } , { " i d ": CATEGORY_ID, " categoryName ": CATEGORY_NAME } . . . ]

3.1.6.2.2 Aggiunta di una Categoria

Quando l’amministratore procede con l’inserimento di una nuova categoria, l’applicativo effettua la richiesta al seguente endpoint:

(39)

Tale richiesta può essere effettuata solo dall’amministratore globale in quanto solo egli può inserire nuove categorie; l’header della richiesta deve quindi contenere il token che identifica l’amministratore, come segue:

Authorization Bearer TOKEN

Il corpo della richiesta deve contenere il nome da assegnare alla nuova categoria e deve rispecchiare la seguente struttura:

{

" categoryName ": CATEGORY_NAME }

Se invece si tenta di inserire una categoria già presente nel database, il server ritornerà la seguente risposta:

{

" timestamp ": TIMESTAMP,

" s t a t u s ": 400 ,

" e r r o r ": " Bad Request " ,

" message ": " Category w i t h CategoryName ’CATEGORY_NAME’ a l r e a d y e x i s t s " ,

" path ": " / c a t e g o r i e s " }

Se infine l’aggiunta di una nuova categoria avviene con successo, la risposta conterrà la categoria appena creata.

3.1.6.2.3 Modifica di una Categoria

Quando l’amministratore effettua una modifica ad una determinata categoria, l’applicativo effettua la richiesta al seguente endpoint:

PUT /category/CATEGORY_ID

Tale richiesta può essere effettuata solo dall’amministratore globale in quanto solo egli può inserire modificare una categoria; l’header della richiesta deve quindi contenere il token che identifica l’amministratore, come segue:

Authorization Bearer TOKEN

Il corpo della richiesta deve contenere il nome da assegnare alla categoria e deve rispec-chiare la seguente struttura:

{

" categoryName ": CATEGORY_NAME }

Se si cerca di modificare una categoria non esistente, la risposta del server seguirà la seguente struttura:

(40)

32 Implementazione

{

" timestamp ": TIMESTAMP,

" s t a t u s ": 404 ,

" e r r o r ": " Not Found " ,

" message ": " Category n o t found w i t h i d : CATEGORY_ID " ,

" path ": " / c a t e g o r y / CATEGORY_ID" }

Se invece si tenta di assegnare alla categoria un nome di una categoria già presente nel database, il server ritornerà la seguente risposta:

{

" timestamp ": TIMESTAMP,

" s t a t u s ": 400 ,

" e r r o r ": " Bad Request " ,

" message ": " Category w i t h CategoryName ’CATEGORY_NAME’ a l r e a d y e x i s t s " ,

" path ": " / c a t e g o r y / CATEGORY_ID" }

Se infine la modifica di una categoria avviene con successo, la risposta conterrà la categoria appena modificata.

3.1.6.2.4 Rimozione di una Categoria

Se l’amministratore decide di eliminare una categoria, l’applicativo effettua la richiesta al seguente endpoint:

DELETE /category/CATEGORY_ID

Tale richiesta può essere effettuata solo dall’amministratore globale in quanto solo egli può inserire eliminare una categoria; l’header della richiesta deve quindi contenere il token che identifica l’amministratore, come segue:

Authorization Bearer TOKEN

Se si cerca di eliminare una categoria non esistente, la risposta del server seguirà la seguente struttura:

{

" timestamp ": TIMESTAMP,

" s t a t u s ": 404 ,

" e r r o r ": " Not Found " ,

" message ": " Category n o t found w i t h i d : CATEGORY_ID " ,

" path ": " / c a t e g o r y / CATEGORY_ID" }

Se la cancellazione di una categoria avviene con successo, la risposta conterrà il messaggio “Category Deleted”.

(41)

3.1.6.2.5 Recupero delle Sottocategorie

L’applicativo recupera le sottocategorie appartenenti ad una determinata categoria tramite il seguente endpoint:

GET /category/CATEGORY_ID/subcategories

La visione delle sottocategorie deve essere accessibile ad ogni utente quindi non è neces-sario fornire alcun Authorization Token.

La risposta del server contiene la lista delle sottocategorie presenti nel database, con relativi identificativi e categoria da cui discende:

[ { " i d ": SUBCATEGORY_ID, " subcategoryName ": SUBCATEGORY_NAME, " c a t e g o r y ": { " i d ": CATEGORY_ID, " categoryName ": CATEGORY_NAME } } , { " i d ": SUBCATEGORY_ID, " subcategoryName ": SUBCATEGORY_NAME, " c a t e g o r y ": { " i d ": CATEGORY_ID, " categoryName ": CATEGORY_NAME } } . . . ]

3.1.6.2.6 Aggiunta di una Sottocategoria

Quando l’amministratore aggiunge una nuova sottocategoria ad una determinata categoria, l’applicativo effettua la richiesta al seguente endpoint:

POST /category/CATEGORY_ID/subcategories

Tale richiesta può essere effettuata solo dall’amministratore globale in quanto solo egli può inserire nuove sottocategorie; l’header della richiesta deve quindi contenere il token che identifica l’amministratore, come segue:

Authorization Bearer TOKEN

Il corpo della richiesta deve contenere il nome da assegnare alla nuova categoria.

Se si tenta di aggiungere una sottocategoria ad una categoria non esistente, la risposta del server seguirà la seguente struttura:

(42)

34 Implementazione

{

" timestamp ": TIMESTAMP,

" s t a t u s ": 404 ,

" e r r o r ": " Not Found " ,

" message ": " Category n o t found w i t h i d : CATEGORY_ID " ,

" path ": " / c a t e g o r y / CATEGORY_ID / s u b c a t e g o r i e s " }

Se invece si tenta di inserire una sottocategoria già presente nel database, il server ritornerà la seguente risposta:

{

" timestamp ": TIMESTAMP,

" s t a t u s ": 400 ,

" e r r o r ": " Bad Request " ,

" message ": " Subcategory w i t h SubcategoryName ’SUBCATEGORY_NAME’ a l r e a d y e x i s t s " ,

" path ": " / c a t e g o r y / CATEGORY_ID / s u b c a t e g o r i e s " }

Se infine l’aggiunta di una sottocategoria ad una categoria avviene con successo, la risposta conterrà la sottocategoria appena creata.

3.1.6.2.7 Modifica di una Sottocategoria

Quando l’amministratore effettua una modifica ad una determinata sottocategoria, l’applica-tivo effettua la richiesta al seguente endpoint:

PUT /subcategory/SUBCATEGORY_ID

Tale richiesta può essere effettuata solo dall’amministratore globale in quanto solo egli può inserire modificare una categoria; l’header della richiesta deve quindi contenere il token che identifica l’amministratore, come segue:

Authorization Bearer TOKEN

Il corpo della richiesta deve contenere il nome da assegnare alla sottocategoria.

Se si cerca di modificare una sottocategoria non esistente, la risposta del server seguirà la seguente struttura:

{

" timestamp ": TIMESTAMP,

" s t a t u s ": 404 ,

" e r r o r ": " Not Found " ,

" message ": " Subcategory n o t found w i t h i d : SUBCATEGORY_ID" ,

" path ": " / s u b c a t e g o r y / SUBCATEGORY_ID" }

Se invece si tenta di assegnare alla sottocategoria un nome di una sottocategoria già presente nel database, il server ritornerà la seguente risposta:

(43)

{

" timestamp ": TIMESTAMP,

" s t a t u s ": 400 ,

" e r r o r ": " Bad Request " ,

" message ": " Subcategory w i t h SubcategoryName ’SUBCATEGORY_NAME’ a l r e a d y e x i s t s " ,

" path ": " / s u b c a t e g o r y / SUBCATEGORY_ID" }

Se infine la modifica di una sottocategoria avviene con successo, la risposta conterrà la sottocategoria appena modificata.

3.1.6.2.8 Rimozione di una Sottocategoria

Se l’amministratore decide di eliminare una sottocategoria, l’applicativo effettua la richiesta al seguente endpoint:

DELETE /subcategory/SUBCATEGORY_ID

Tale richiesta può essere effettuata solo dall’amministratore globale in quanto solo egli può inserire eliminare una sottocategoria; l’header della richiesta deve quindi contenere il token che identifica l’amministratore, come segue:

Authorization Bearer TOKEN

Se si cerca di eliminare una sottocategoria non esistente, la risposta del server seguirà la seguente struttura:

{

" timestamp ": TIMESTAMP,

" s t a t u s ": 404 ,

" e r r o r ": " Not Found " ,

" message ": " Subcategory n o t found w i t h i d : SUBCATEGORY_ID" ,

" path ": " / s u b c a t e g o r y / SUBCATEGORY_ID" }

Se la cancellazione di una sottocategoria avviene con successo, la risposta conterrà il messaggio “Subcategory Deleted”.

3.1.6.3 Courserun

Accedendo alla pagina dedicata è possibile consultare le informazioni riguardanti i corsi presenti nel database. Questa funzionalità è accessibile anche senza aver effettuato il login. Ai normali utenti è concessa solo la visione delle informazioni sui corsi; l’amministratore globale e l’amministratore dell’organizzazione che offre il corso possono invece modificare la categoria, la sottocategoria assegnata al corso e una nota relativa a quest’ultimo.

(44)

36 Implementazione

organizzazione, titolo, immagine, descrizione, data d’inizio, data di fine, ritmo del corso, data d’inizio iscrizione, data di fine iscrizione, lingua, riepilogo, categoria, sottocategoria e nota.

3.1.6.3.1 Recupero dei Courserun

Accedendo alla sezione dedicata, l’applicativo recupera i corsi presenti nel sistema tramite il seguente endpoint:

GET /courserun

La visione dei corsi deve essere accessibile ad ogni utente, anche se non autenticati, quindi non è necessario fornire alcun Authorization Token.

La risposta del server contiene la lista dei corsi presenti nel database, rispecchiando la seguente struttura: [ { " u u i d ": UUID , " c o u r s e _ u u i d ": COURSE_UUID, " o r g a n i z a t i o n ": ORGANIZATION , " t i t l e ": TITLE , " i m a g e u r l ": IMAGEURL, " s h o r t _ d e s c r i p t i o n ": DESCRIPTION , " s t a r t ": DATE_START, " end ": DATE_END, " p a c i n g _ t y p e ": PACING_TYPE , " e n r o l l m e n t _ s t a r t ": ENROLLMENT_START, " e n r o l l m e n t _ e n d ": ENROLLMENT_END, " language ": LANGUAGE, " o v e r v i e w ": OVERVIEW, " c a t e g o r y ": CATEGORY, " s u b c a t e g o r y ": SUBCATEGORY, " note ": NOTE } . . . ] 3.1.6.3.2 Modifica di un Courserun

Quando l’amministratore globale o dell’organizzazione che offre il corso modifica la catego-ria, lo sottocategoria o la nota del suddetto corso, viene effettuata una richiesta al seguente endpoint:

(45)

Dove COURSE_ID corrisponde all’uuid dell’istanza del corso che si intende modificare. Dato che solo l’amministratore globale e dell’organizzazione che offre il corso possono ef-fettuare tale richiesta, l’header di quest’ultima deve contenere il token che identifica l’ammi-nistratore, come segue:

Authorization Bearer TOKEN

Il corpo della richiesta deve contenere le informazioni aggiornate del corso che si intende modificare, rispecchiando la seguente struttura:

{ " u u i d ": UUID , " c o u r s e _ u u i d ": COURSE_UUID, " o r g a n i z a t i o n ": ORGANIZATION , " t i t l e ": TITLE , " i m a g e u r l ": IMAGEURL, " s h o r t _ d e s c r i p t i o n ": DESCRIPTION , " s t a r t ": DATE_START, " end ": DATE_END, " p a c i n g _ t y p e ": PACING_TYPE , " e n r o l l m e n t _ s t a r t ": ENROLLMENT_START, " e n r o l l m e n t _ e n d ": ENROLLMENT_END, " language ": LANGUAGE, " o v e r v i e w ": OVERVIEW, " c a t e g o r y ": CATEGORY, " s u b c a t e g o r y ": SUBCATEGORY, " note ": NOTE }

Se si cerca di modificare un corso ma non si hanno abbastanza privilegi per effettuare tale operazione, la risposta del server avrà la seguente struttura:

{

" timestamp ": TIMESTAMP,

" s t a t u s ": 400 ,

" e r r o r ": " Bad Request " ,

" message ": " Sorry , you don ’ t have enough p r i v i l e g e s " ,

" path ": " / c o u r s e r u n / COURSE_ID / e d i t " }

Se si cerca di modificare un corso non presente nel sistema, la risposta del server avrà la seguente struttura:

{

" timestamp ": TIMESTAMP,

" s t a t u s ": 404 ,

(46)

38 Implementazione

" message ": " Course n o t found w i t h i d : ’COURSE_ID ’ " ,

" path ": " / c o u r s e r u n / COURSE_ID / e d i t " }

Nel corpo della richiesta, nei campi category e subcategory è necessario inserire la cate-goria e la sottocatecate-goria che si intende assegnare al corso. Se la catecate-goria/sottocatecate-goria inserita non è presente nel sistema, la risposta del server avrà la seguente struttura:

{

" timestamp ": TIMESTAMP,

" s t a t u s ": 404 ,

" e r r o r ": " Not Found " ,

" message ": " Category / Subcategory n o t found w i t h i d : ’ 1 2 3 4 5 ’ " ,

" path ": " / c o u r s e r u n / COURSE_ID / e d i t " }

3.1.6.4 Contenuto della pagina principale

La pagina principale contiene un’introduzione al sito, le caratteristiche principali del servizio che si intende offrire, una lista di citazioni ottenute dal servizio e la lista dei partners. Come richiesto dal committente, il contenuto della pagina iniziale deve poter essere cabile dall’amministratore quindi sono stati predisposti endpoints per il recupero e la modifi-ca di ogni elemento che modifi-caratterizza la pagina principale.

Il recupero è accessibile ad ogni utente mentre la modifica è limitata al solo amministratore globale.

3.1.6.4.1 Recupero dell’introduzione

L’applicativo recupera l’introduzione da visualizzare nella pagina principale tramite il seguen-te endpoint:

GET /maincontent/introduction

La visualizzazione dell’introduzione deve essere accessibile ad ogni utente quindi non è necessario fornire alcun Authorization Token.

La risposta del server contiene il testo rappresentante l’introduzione al sito.

3.1.6.4.2 Modifica dell’introduzione

Se l’amministratore decide di modificare l’introduzione, l’applicativo effettua la richiesta al seguente endpoint:

PUT /maincontent/introduction

Tale richiesta può essere effettuata solo dall’amministratore generale. L’header della richie-sta deve quindi contenere il token che identifica l’amministratore, come segue:

(47)

Authorization Bearer TOKEN

La risposta del server include il contenuto testuale della pagina iniziale comprendente l’in-troduzione appena modificata e features, rispecchiando la seguente struttura:

{

" i d ": ID ,

" i n t r o d u c t i o n ": INTRODUCTION ,

" f e a t u r e s ": FEATURES }

3.1.6.4.3 Recupero delle features

L’applicativo recupera le caratteristiche principali del servizio, da visualizzare nella pagina principale, tramite il seguente endpoint:

GET /maincontent/features

La visualizzazione delle features deve essere accessibile ad ogni utente quindi non è ne-cessario fornire alcun Authorization Token.

La risposta del server contiene il testo rappresentante le features del servizio.

3.1.6.4.4 Modifica delle features

Se l’amministratore decide di modificare la sezione features, l’applicativo effettua la richiesta al seguente endpoint:

PUT /maincontent/features

Tale richiesta può essere effettuata solo dall’amministratore globale. L’header della richiesta deve quindi contenere il token che identifica l’amministratore, come segue:

Authorization Bearer TOKEN

La risposta del server include il contenuto testuale della pagina iniziale comprendente l’in-troduzione e la sezione features appena modificata, rispecchiando la seguente struttura:

{

" i d ": ID ,

" i n t r o d u c t i o n ": INTRODUCTION ,

" f e a t u r e s ": FEATURES }

3.1.6.4.5 Recupero delle citazioni

L’applicativo recupera la lista delle citazioni da visualizzare nella pagina principale tramite il seguente endpoint:

(48)

40 Implementazione

GET /maincontent/press

La visualizzazione delle citazioni deve essere accessibile ad ogni utente quindi non è ne-cessario fornire alcun Authorization Token.

La risposta del server contiene la lista delle citazioni presenti nel database. Ciascuna cita-zione è caratterizzata da un identificativo, da un commento, da un autore e da un link. La risposta rispecchia la seguente struttura:

[ { " i d ": QUOTES_ID , " comment ": COMMENT, " a u t h o r ": AUTHOR, " l i n k ": LINK } . . . ]

3.1.6.4.6 Aggiunta di una citazione

Quando l’amministratore decide di aggiungere una nuova citazione, l’applicativo effettua la richiesta al seguente endpoint:

POST /maincontent/press

Tale richiesta può essere effettuata solo dall’amministratore globale. L’header richiesta deve quindi contenere il token che identifica l’amministratore, come segue:

Authorization Bearer TOKEN

Il corpo della richiesta deve contenere le informazioni riguardanti la citazione che si intende aggiungere, in particolare commento, autore e link, rispecchiando la seguente struttura:

{

" comment ": COMMENT,

" a u t h o r ": AUTHOR,

" l i n k ": LINK }

La risposta del server contiene le informazioni della citazione appena aggiunta al database.

3.1.6.4.7 Modifica di una citazione

Se l’amministratore decide di modificare una determinata citazione, l’applicativo effettua la richiesta al seguente endpoint:

PUT /maincontent/press/QUOTES_ID/edit

Tale richiesta può essere effettuata solo dall’amministratore globale. L’header deve quindi contenere il token che identifica l’amministratore, come segue:

(49)

Authorization Bearer TOKEN

Il corpo della richiesta deve contenere le informazioni riguardanti la citazione che si intende modificare, in particolare commento, autore e link, rispecchiando la seguente struttura:

{

" comment ": COMMENT,

" a u t h o r ": AUTHOR,

" l i n k ": LINK }

La risposta del server contiene le informazioni della citazione appena modificata.

Se si cerca di modificare una citazione non presente nel sistema, specificando cioè un identificativo non corrispondente a nessuna citazione, la risposta del server avrà la seguente struttura:

{

" timestamp ": TIMESTAMP,

" s t a t u s ": 404 ,

" e r r o r ": " Not Found " ,

" message ": " Press Comment n o t found w i t h i d : QUOTES_ID " ,

" path ": " / m a i n c o n t e n t / p re ss / QUOTES_ID / e d i t " }

3.1.6.4.8 Rimozione di una citazione

Se l’amministratore decide di eliminare una determinata citazione, l’applicativo effettua la richiesta al seguente endpoint:

DELETE /maincontent/press/QUOTES_ID/delete

Tale richiesta può essere effettuata solo dall’amministratore globale. L’header deve quindi contenere il token che identifica l’amministratore, come segue:

Authorization Bearer TOKEN

In caso di rimozione avvenuta con successo il server risponde con il messaggio “Press Comment deleted”.

Se invece si cerca di eliminare una citazione non presente nel sistema, specificando cioè come in precedenza un identificativo non corrispondente a nessuna citazione, la risposta del server avrà la seguente struttura:

{

" timestamp ": TIMESTAMP,

" s t a t u s ": 404 ,

" e r r o r ": " Not Found " ,

Riferimenti

Documenti correlati

IDROPULITRICI AD ACQUA FREDDA, AD ACQUA CALDA, INDUSTRIALI, AUTONOME, IDROPULITRICI E ACCESSORI SPECIFICI PER LA PULIZIA DEL

Il contatto diretto nel «Double-Bubble» è possibile solo con norme di sicurezza più severe (mascherina FFP2, guanti, limitazione della durata del contatto ecc.) Per ogni serie

trasferimento di know how, affiancamento ai vari enti con studenti e funzionari,.. realizzazione di un catalogo unico dei

S e viaggi con tutta la famiglia e ti piacciono le favole per bambini, questa brochure ti entusiasmerà, perché i Family Hotels sono interamente dedicati alle esigenze delle

Mostrano alberghi, musei, monumenti, mercati, trasporti pubblici, attrazioni turistiche e punti di interesse, le statistiche utili, temperature, precipitazioni ore di sole

Può dunque accadere che nell’orario annuale la corsa x nel giorno y risulti «normale», ma che un orario periodico introduca un adattamento per la corsa x nel giorno y (ad es.

In questo capitolo, ci occuperemo di un torneo svizzero individuale (opzione “Sistema Svizzero”).. apparirà in chess-results.com, se scegliete di pubblicarlo), il

Se i prodotti sono caricati “Da Modelli Carrello” potranno essere raggruppati scegliendo tra i campi presenti in anagrafica prodotti IDEA (es. categoria, sotto-categoria,