1
Fork 0
mirror of https://github.com/Steffo99/sophon.git synced 2024-10-16 07:07:26 +00:00

🔨 Move around some files

This commit is contained in:
Steffo 2021-11-14 04:28:50 +01:00
parent 2aa369efbf
commit 66c94d4c87
Signed by: steffo
GPG key ID: 6965406171929D01
134 changed files with 3151 additions and 7 deletions

2
.gitignore vendored
View file

@ -1,2 +1,2 @@
proxy.dbm
docs/build
thesis/build

View file

@ -17,11 +17,13 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/sophon" isTestSource="false" />
</content>
<content url="file://$MODULE_DIR$/../docs">
<sourceFolder url="file://$MODULE_DIR$/../docs/source" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../docs/source/_static" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/../docs/build" />
<excludeFolder url="file://$MODULE_DIR$/../docs/source/_extra" />
<content url="file://$MODULE_DIR$/../report">
<sourceFolder url="file://$MODULE_DIR$/../report/source" isTestSource="false" />
</content>
<content url="file://$MODULE_DIR$/../thesis">
<sourceFolder url="file://$MODULE_DIR$/../thesis/source" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/../thesis/build" />
<excludeFolder url="file://$MODULE_DIR$/../thesis/source/_extra" />
</content>
<orderEntry type="jdk" jdkName="Poetry (backend) (3)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
@ -31,7 +33,7 @@
<option name="TEMPLATE_FOLDERS">
<list>
<option value="$MODULE_DIR$/sophon/templates" />
<option value="$MODULE_DIR$/../docs/source/_templates" />
<option value="$MODULE_DIR$/../thesis/source/_templates" />
</list>
</option>
</component>

View file

@ -0,0 +1,22 @@
Il progetto in breve
********************
*Sophon* è una applicazione web realizzata nel 2021 da Stefano Pigozzi per conto del `dipartimento di Informatica`_ dell'`Università di Modena e Reggio Emilia`_.
Sophon permette ai suoi utenti di effettuare in sicurezza attività di ricerca collaborativa da remoto, sfruttando le macchine dell'istituzione di loro appartenenza per l'elaborazione dei dati.
.. _dipartimento di Informatica: https://www.fim.unimore.it/
.. _Università di Modena e Reggio Emilia: https://www.unimore.it/
Screenshots
===========
.. image:: ../2_concepts/1_instances/choose.png
.. image:: ../2_concepts/2_users/login.png
.. image:: ../2_concepts/3_researchgroups/list.png
.. image:: ../2_concepts/4_researchprojects/list.png
.. image:: ../2_concepts/5_notebooks/list.png
.. image:: ../2_concepts/5_notebooks/detail.png
.. image:: ../2_concepts/5_notebooks/inside_the_lab.png
.. image:: ../../2_admin/2_administration/admin_home.png

BIN
report/source/1_user/2_concepts/1_instances/choose.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/1_user/2_concepts/1_instances/diagram.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,26 @@
Istanza
=======
Un'*istanza* rappresenta un'**installazione di Sophon** effettuata su un server di un'istituzione di ricerca, come ad esempio un'Università.
Ogni istanza è **fisicamente e logicamente separata** dalle altre; istanze diverse **non condividono alcun dato** tra loro.
.. image:: diagram.png
:width: 400
URL dell'istanza
----------------
Ciascuna istanza è accessibile tramite **uno specifico URL**, deciso dall'amministratore di sistema al momento dell'installazione.
.. image:: urls.png
:width: 400
Istanze nell'interfaccia web
----------------------------
L'interfaccia web di Sophon permette di **selezionare l'istanza** che si desidera usare inserendo il corrispondente URL.
.. image:: choose.png

BIN
report/source/1_user/2_concepts/1_instances/urls.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/1_user/2_concepts/2_users/creation.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/1_user/2_concepts/2_users/diagram.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,58 @@
Utente
======
Un *utente* è una entità che interagisce con una specifica istanza Sophon: ad esempio, un utente potrebbe essere una persona fisica, oppure potrebbe essere un software di automazione che si interfaccia con Sophon.
.. image:: diagram.png
:width: 400
Livelli di accesso
------------------
Un utente può avere uno dei seguenti *livelli di accesso*:
Superutente
^^^^^^^^^^^
Utente con accesso completo a ogni singola risorsa sull'istanza Sophon, tipicamente riservato per l'amministratore di sistema.
Utente
^^^^^^
Utente con permessi limitati alle risorse che ha creato o a cui è stato fornito accesso.
Ospite
^^^^^^
Utente che può visualizzare alcuni contenuti dell'istanza Sophon ma non può interagirci.
Credenziali di accesso
----------------------
Gli utenti di tipo :ref:`Utente` e :ref:`Superutente` devono identificarsi sull'istanza con le loro credenziali.
Di default, le credenziali sono un **nome utente** e una **password**, ma è possibile che l'amministratore di sistema implementi un sistema diverso, ad esempio un sistema `Single Sign-On`_.
.. _Single Sign-On: https://it.wikipedia.org/wiki/Single_sign-on
Creazione di nuovi utenti
-------------------------
In un':ref:`istanza` Sophon, la registrazione autonoma **non è permessa**: nuovi utenti possono essere creati esclusivamente da un :ref:`superutente` all'interno del pannello di amministrazione.
.. image:: creation.png
Utenti nell'interfaccia web
---------------------------
Dopo aver selezionato un':ref:`istanza`, l'interfaccia web di Sophon permette di **effettuare l'accesso** come la tipologia di utente con la quale si intende utilizzare il servizio.
.. image:: login.png

BIN
report/source/1_user/2_concepts/2_users/login.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/1_user/2_concepts/3_researchgroups/choose.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
report/source/1_user/2_concepts/3_researchgroups/diagram.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/1_user/2_concepts/3_researchgroups/icons.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,69 @@
Gruppo di ricerca
=================
Un *gruppo di ricerca* rappresenta un insieme di utenti che collaborano su uno o più progetti.
.. image:: diagram.png
:width: 400
Membri e modalità di accesso
----------------------------
Gli utenti dell':ref:`istanza` possono diventare *membri* dei gruppi di ricerca, con una delle seguenti modalità selezionate nelle impostazioni del gruppo:
- se il gruppo è *aperto*, allora qualsiasi utente può diventarne membro semplicemente **facendo richiesta** attraverso l'interfaccia web;
.. image:: join_open.png
- se il gruppo è in *modalità manuale*, allora nessun utente potrà richiedere di unirsi, e i membri saranno **selezionati manualmente** dal creatore del gruppo.
.. image:: join_manual.png
Nell'interfaccia web, i gruppi aperti sono marcati con l'icona di un **globo 🌐**, mentre i gruppi in modalità manuale sono marcati con l'icona di una **busta ✉️**.
.. image:: icons.png
In qualsiasi momento, i membri di un gruppo possono **lasciarlo** facendo richiesta attraverso l'interfaccia web.
Creazione di nuovi gruppi
-------------------------
Qualsiasi :ref:`utente` può **creare** gruppi di ricerca dall'interfaccia web.
.. image:: creation.png
Modifica di gruppi
------------------
Il creatore di un gruppo di ricerca è l'unico :ref:`utente` che può cambiarne **nome**, **descrizione**, **membri** e **modalità di accesso**.
Lo *slug*, l'identificatore univoco del gruppo, non è modificabile successivamente alla creazione, in quanto è utilizzato all'interno degli URL, che devono essere immutabili.
Eliminazione di gruppi
----------------------
Il creatore di un gruppo è l'unico utente in grado di **cancellare** il gruppo che ha creato.
.. warning::
L'eliminazione di un gruppo è un'operazione distruttiva non reversibile!
.. hint::
Se si è i creatori di un gruppo, e si vuole trasferire il gruppo ad un altro utente, sarà necessario fare richiesta ad un :ref:`superutente` di cambiare il proprietario del gruppo all'interno del pannello di amministrazione.
.. seealso::
:ref:`Conferma di eliminazione`
Gruppi nell'interfaccia web
---------------------------
Dopo aver effettuato l'accesso come :ref:`utente` o :ref:`ospite`, l'interfaccia utente di Sophon visualizza l'elenco di gruppi di ricerca disponibili nell':ref:`istanza`, permettendo agli utenti di unirsi ad essi, lasciarli, oppure eliminarli.
.. image:: list.png

Binary file not shown.

Binary file not shown.

BIN
report/source/1_user/2_concepts/3_researchgroups/list.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
report/source/1_user/2_concepts/4_researchprojects/icons.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,68 @@
Progetto di ricerca
===================
Un *progetto di ricerca* rappresenta una **collezione di oggetti** relativa a un singolo argomento mantenuta da un :ref:`gruppo di ricerca`.
.. image:: diagram.png
:width: 400
Visibilità dei progetti
-----------------------
I progetti hanno tre diverse impostazioni di visibilità che regolano chi può visualizzarne i contenuti:
.. glossary::
Progetto privato
Il progetto è visibile solo ai membri del gruppo a cui appartiene il progetto.
Progetto interno
Il progetto è visibile solo agli :term:`utenti` dell'istanza, e non agli :term:`ospiti`.
Progetto pubblico
Il progetto è visibile a tutti.
I progetti privati sono marcati con l'icona di un **lucchetto chiuso 🔒**, i progetti interni con l'icona di un **università 🏦** e i progetti pubblici con l'icona di un **globo 🌐**.
.. image:: icons.png
Creazione di nuovi progetti
---------------------------
Qualsiasi *membro* di un :ref:`gruppo di ricerca` può creare nuovi progetti.
.. image:: creation.png
Modifica di progetti
--------------------
Qualsiasi *membro* di un :ref:`gruppo di ricerca` può modificare **nome**, **descrizione** dei progetti al suo interno.
Solo il *creatore del gruppo* può modificarne la **visibilità**, o **trasferire il progetto ad un altro gruppo**.
Lo *slug*, l'identificatore univoco del progetto, non è modificabile successivamente alla creazione, in quanto è utilizzato all'interno degli URL, che devono essere immutabili.
Eliminazione di progetti
------------------------
Qualsiasi *membro* di un :ref:`gruppo di ricerca` può eliminare i progetti al suo interno.
.. warning::
L'eliminazione di un progetto è un'operazione distruttiva non reversibile!
.. seealso::
:ref:`Conferma di eliminazione`
Progetti nell'interfaccia web
-----------------------------
Dopo aver selezionato un :ref:`gruppo di ricerca`, l'interfaccia web mostra i progetti visibili all':term:`utente` attuale, e gli permette di selezionarne uno oppure di eliminarli.
.. image:: list.png

BIN
report/source/1_user/2_concepts/4_researchprojects/list.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/1_user/2_concepts/5_notebooks/action_lock.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/1_user/2_concepts/5_notebooks/action_start.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/1_user/2_concepts/5_notebooks/action_stop.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
report/source/1_user/2_concepts/5_notebooks/connection.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/1_user/2_concepts/5_notebooks/creation.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/1_user/2_concepts/5_notebooks/detail.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/1_user/2_concepts/5_notebooks/diagram.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,155 @@
Notebook
========
Un *notebook* rappresenta una **postazione di lavoro** che può essere allegata ad un :ref:`progetto di ricerca`.
.. image:: diagram.png
:width: 400
Creazione di nuovi notebook
---------------------------
Qualsiasi **membro** di un :ref:`gruppo di ricerca` può creare nuovi notebook all'interno di uno dei progetti del gruppo a cui appartiene.
.. image:: creation.png
.. note::
Per motivi tecnici, i notebook non possono avere come slug ``backend``, ``frontend``, ``proxy``, ``api``, ``static`` e ``src``, oppure iniziare o terminare con un trattino ``-``.
Stato del notebook
------------------
Un notebook può essere *avviato* o *fermo* in base al suo stato di esecuzione sull':ref:`istanza` Sophon:
- è *avviato* se sta venendo eseguito ed è accessibile;
.. image:: status_stopped.png
:height: 40
- è *fermo* se non sta venendo eseguito o sta venendo preparato.
.. image:: status_running.png
:height: 40
Alla creazione, un notebook è *fermo*.
Avviare un notebook
^^^^^^^^^^^^^^^^^^^
Un **membro** del :ref:`gruppo di ricerca` a cui appartiene il notebook può richiedere al server l'avvio di quest'ultimo, in modo da poterlo utilizzare successivamente.
.. image:: action_start.png
Fermare un notebook
^^^^^^^^^^^^^^^^^^^
Un **membro** del :ref:`gruppo di ricerca` a cui appartiene il notebook può richiedere al server l'arresto di quest'ultimo, salvando i dati e interrompendo la sessione di lavoro attualmente in corso.
.. image:: action_stop.png
.. warning::
Se un notebook viene fermato durante un upload o download di file, essi risulteranno corrotti e saranno da ritrasferire.
Immagine del notebook
---------------------
In **fase di creazione** di un notebook, oppure mentre esso è **fermo**, è possibile selezionare un'*immagine*, ovvero il programma che sarà eseguito dal notebook all'avvio.
Attualmente, l'unica immagine configurata è **Jupyter (Sophon)**, che esegue un server `Jupyter`_ con un'interfaccia `JupyterLab`_.
.. _Jupyter: https://jupyter.org/
.. _JupyterLab: https://jupyterlab.readthedocs.io/en/stable/
Collegarsi a un notebook
------------------------
I **membri** del :ref:`gruppo di ricerca` a cui appartiene il notebook possono connettersi ad un notebook **avviato** attraverso un URL segreto comunicatogli dall':ref:`istanza`.
.. image:: connection.png
Utilizzo di un notebook
^^^^^^^^^^^^^^^^^^^^^^^
Una volta connessi ad un notebook, sarà visualizzato il programma eseguito dall'immagine selezionata.
.. seealso::
Per informazioni su come usare JupyterLab, è possibile consultare l'apposita `documentazione <https://jupyterlab.readthedocs.io/en/stable/>`_.
Collaborazione
^^^^^^^^^^^^^^
È possibile il collegamento **simultaneo** di più membri al notebook: l'immagine selezionata permetterà loro di collaborare in tempo reale sugli stessi file.
.. image:: collaboration.png
Blocco di un notebook
---------------------
Qualsiasi **membro** del :ref:`gruppo di ricerca` a cui appartiene il notebook può *bloccarlo* per segnalare agli altri utenti che vi hanno accesso di non utilizzare quello specifico notebook.
.. image:: action_lock.png
Bloccare un notebook **rimuove dall'interfaccia web** i bottoni per l'avvio, l'arresto, l'eliminazione al notebook bloccato, e, per tutti tranne l':ref:`utente` che ha effettuato la richiesta, anche il bottone per la connessione.
.. image:: locked.png
.. warning::
Il blocco di un notebook è solo estetico, e non impedisce agli utenti di effettuare queste operazioni tramite strumenti esterni, come la Console per sviluppatori del browser web.
Un notebook bloccato potrà essere sbloccato da qualsiasi **membro** del :ref:`gruppo di ricerca`; il membro che ha richiesto il blocco potrà sbloccarlo **immediatamente**, mentre agli altri membri sarà richiesto di confermare l'azione come se stesse venendo effettuata un'eliminazione.
.. seealso::
:ref:`Conferma di eliminazione`
Isolamento dei notebook
-----------------------
I notebook risiedono tutti sullo **stesso elaboratore fisico** che esegue l':ref:`istanza` Sophon, pertanto ne condividono le risorse, come processore, scheda video e memoria.
Sono però **logicamente isolati**: i file contenuti in un notebook non sono accessibili agli altri, e i notebook non hanno modo di comunicare direttamente tra loro.
.. image:: diagram_network.png
:width: 400
Modifica di un notebook
-----------------------
Qualsiasi *membro* di un :ref:`gruppo di ricerca` può modificare **nome** e **immagine** dei notebook *fermi* al suo interno.
I notebook *avviati* non possono essere modificati.
Lo *slug*, l'identificatore univoco del notebook, non è modificabile successivamente alla creazione, in quanto è utilizzato all'interno degli URL, che devono essere immutabili.
Eliminazione di un notebook
---------------------------
Qualsiasi *membro* di un :ref:`gruppo di ricerca` può eliminare i notebook all'interno dei progetti del gruppo, a condizione che questi siano *fermi* e *non bloccati*.
Notebook nell'interfaccia web
-----------------------------
Dopo aver selezionato un :ref:`progetto di ricerca`, l'interfaccia web mostra l'elenco dei notebook che gli appartengono, assieme alle azioni che è possibile effettuare su di essi.
.. image:: list.png
È possibile selezionare un notebook per visualizzarne i dettagli o connettercisi.
.. image:: detail.png

Binary file not shown.

BIN
report/source/1_user/2_concepts/5_notebooks/locked.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
report/source/1_user/2_concepts/diagram_full.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,15 @@
I concetti
**********
Questa sezione illustra i concetti chiave di Sophon e il loro funzionamento.
.. toctree::
:maxdepth: 1
1_instances/index
2_users/index
3_researchgroups/index
4_researchprojects/index
5_notebooks/index
.. image:: diagram_full.png

BIN
report/source/1_user/3_extras/confirm.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,72 @@
Dettagli dell'interfaccia web
*****************************
Sono elencate in questo capitolo alcuni dettagli interessanti relativi all'intera interfaccia web.
Markdown nelle descrizioni
==========================
Le descrizioni dell':ref:`istanza`, del :ref:`gruppo di ricerca` selezionato e del :ref:`progetto di ricerca` selezionato sono interpretate dall'interfaccia web come `Markdown`_, un semplice e comune linguaggio di marcatura del testo con varie funzionalità che possono essere utili per descrivere l'entità in questione o lasciare messaggi agli altri collaboratori.
Si fornisce un breve riassunto della sintassi di `Markdown`_.
.. code-block:: markdown
<!-- Commento, non viene visualizzato -->
<!-- Titoli -->
# Parte
## Capitolo
### Sezione
#### Sottosezione
##### Sottosottosezione
###### Paragrafo
<!-- Formattazione -->
**grassetto**
*corsivo*
__sottolineato__
`codice`
<!-- Collegamenti -->
[testo](url)
<!-- Immagini -->
![alt](url)
<!-- Tabelle -->
| Riga 1 | Riga 2 | Riga 3 |
|--------|--------|--------|
| Cella | Cella | Cella |
| Cella | Cella | Cella |
<!-- Codice -->
```linguaggio
def funzione():
pass
```
.. _Markdown: https://daringfireball.net/projects/markdown/syntax
Elenco dei membri
=================
Quando viene selezionato un :ref:`gruppo di ricerca`, viene visualizzato l'elenco dei suoi membri.
Il creatore del :ref:`gruppo di ricerca` è evidenziato in blu, mentre l':ref:`utente` attuale è sottolineato.
.. image:: members_list.png
Conferma di eliminazione
========================
Per impedire eliminazioni accidentali di risorse, è presente un meccanismo di conferma che richiede all'utente di ripremere il tasto di eliminazione trascorsi 3 secondi dalla prima richiesta.
.. image:: confirm.png
.. raw:: html
<p><video width="460" height="232" controls src="../../_static/group_delete_confirm.mp4"></video></p>

BIN
report/source/1_user/3_extras/members_list.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/1_user/admin_login.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/1_user/classic_notebook.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/1_user/screenshots/admin_page.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,21 @@
Requisiti dell'host
===================
- Una connessione ad Internet (solo in fase di installazione)
- `GNU Wget`_ (solo in fase di installazione)
- Un nome di dominio
- Un webserver (ad esempio, `Apache HTTPd`_)
- Un certificato SSL valido *(opzionale, ma raccomandato)*
- `Docker Engine`_
- `Docker Compose`_
.. hint::
È possibile ottenere gratuitamente un certificato SSL utilizzando `Letsencrypt`_!
.. _GNU Wget: https://www.gnu.org/software/wget/
.. _Apache HTTPd: https://httpd.apache.org/
.. _Docker Engine: https://docs.docker.com/engine/
.. _Docker Compose: https://docs.docker.com/compose/
.. _Letsencrypt: https://letsencrypt.org/

View file

@ -0,0 +1,30 @@
Preparazione di Docker Compose
==============================
Come ``root``, si crei una nuova cartella sul proprio sistema operativo in cui archiviare le risorse relative a Sophon:
.. code-block:: console
root:~# mkdir -p /dock/sophon
Successivamente, si scarichi il file ``docker-compose.yml`` all'interno della cartella dal repository di Sophon:
.. code-block:: console
root:~# cd /dock/sophon
root:/dock/sophon# wget "https://raw.githubusercontent.com/Steffo99/sophon/main/docker-compose.yml"
--2021-11-02 18:03:05-- https://raw.githubusercontent.com/Steffo99/sophon/main/docker-compose.yml
SSL_INIT
Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133,
185.199.109.133, 185.199.110.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com) 185.199.108.133:443...
connected.
HTTP request sent, awaiting response... 200 OK
Length: 2957 (2.9K) [text/plain]
Saving to: docker-compose.yml
docker-compose.yml 100%[===================>] 2.89K --.-KB/s in 0s
2021-11-02 18:03:05 (48.0 MB/s) - docker-compose.yml saved [2957/2957]

View file

@ -0,0 +1,17 @@
Configurazione DNS
==================
Si scelga il dominio (o sottodominio) sul quale si vuole che Sophon sia accessibile e si aggiungano i seguenti record DNS, sostituendo il dominio ``ilmiosophon.it`` con il proprio nome di dominio, e gli indirizzi IPv4 e IPv6 del server al posto di `0.0.0.0` e `1234::1234`:
.. code-block:: dns
*.ilmiosophon.it 1800 IN A 0.0.0.0
*.ilmiosophon.it 1800 IN AAAA 1234::1234
ilmiosophon.it 1800 IN A 0.0.0.0
ilmiosophon.it 1800 IN AAAA 1234::1234
Sophon sarà quindi accessibile ai seguenti indirizzi:
- l'interfaccia web al dominio base (``https://ilmiosophon.it/``);
- l'API al dominio base prefisso con ``api.`` (``https://api.ilmiosophon.it/``);
- i notebook al dominio base prefissi con lo slug del notebook (``https://ilmionotebook.ilmiosophon.it/``).

View file

@ -0,0 +1,222 @@
Configurazione ``docker-compose.yml``
=====================================
Si configuri con l'editor di testo preferito il file ``docker-compose.yml`` con le impostazioni desiderate.
.. code-block:: console
root:/dock/sophon# open docker-compose.yml
In particolare, tutte le impostazioni precedute da ``# INSTALL`` vanno obbligatoriamente modificate.
``DJANGO_SECRET_KEY``
---------------------
Specifica la chiave segreta da usare per i cookie di sessione.
.. code-block:: yaml
- DJANGO_SECRET_KEY=do-not-use-this-key-in-production-or-you-will-get-hacked
.. tip::
Un modo facile per impostare la chiave è premere velocemente tasti a caso sulla tastiera!
.. note::
Cambiare la chiave segreta una volta installato Sophon invaliderà tutti gli accessi effettuati dagli utenti.
.. warning::
La chiave segreta è un dato estremamente riservato: chiunque sia a conoscenza della chiave segreta potrà effettuare l'accesso come qualsiasi utente!
.. seealso::
`SECRET_KEY <https://docs.djangoproject.com/en/3.2/ref/settings/#std:setting-SECRET_KEY>`_ nella documentazione di Django.
``DJANGO_PROXY_BASE_DOMAIN``
----------------------------
Specifica il dominio che dovrà essere usato come radice per il proxy, ovvero il dominio per il quale si è configurato il DNS in precedenza.
.. code-block:: yaml
- DJANGO_PROXY_BASE_DOMAIN=ilmiosophon.it
.. note::
Se non è specificato, Sophon verrà eseguito in modalità "sviluppo", e assegnerà porte libere del server ai :ref:`notebook` invece che sottodomini.
.. seealso::
L'opzione :ref:`\`\`APACHE_PROXY_BASE_DOMAIN\`\`` più avanti in questa guida, che deve coincidere con questo valore.
``DJANGO_PROXY_PROTOCOL``
-------------------------
Specifica il protocollo che dovrà essere usato nei mapping del proxy.
Si consiglia vivamente di utilizzare ``https``, ma è un valore valido anche ``http``.
.. code-block:: yaml
- DJANGO_PROXY_PROTOCOL=https
``DJANGO_ALLOWED_HOSTS``
------------------------
Specifica i domini da cui possono provenire le richieste alla pagina di amministrazione.
Per specificare più domini, è necessario separarli con dei pipe ``|`` .
Eccetto in configurazioni speciali, deve essere uguale al dominio prefisso da ``api.``.
.. code-block:: yaml
- DJANGO_ALLOWED_HOSTS=api.ilmiosophon.it
.. seealso::
`ALLOWED_HOSTS <https://docs.djangoproject.com/en/3.2/ref/settings/#allowed-hosts>`_ nella documentazione di Django
``DJANGO_ALLOWED_ORIGINS``
--------------------------
Specifica i domini da cui possono provenire le richieste all'API.
Per specificare più domini, è necessario separarli con dei pipe ``|`` .
Eccetto in configurazioni speciali, deve contenere il proprio dominio prefisso dal protocollo, e in aggiunta il dominio speciale ``https://sophon.steffo.eu``, necessario per permettere l'accesso dall'interfaccia web "universale" di Sophon.
.. code-block:: yaml
- DJANGO_ALLOWED_ORIGINS=https://ilmiosophon.it|https://sophon.steffo.eu
.. seealso::
`Access-Control-Allow-Origin <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin>`_ su MDN
``DJANGO_STATIC_URL``
---------------------
Specifica l'URL a cui saranno accessibili i file statici di Sophon.
Eccetto in configurazioni speciali, deve essere uguale alla seguente stringa, con le parole in maiuscolo sostituite rispettivamente dal protocollo e dal dominio selezionato: ``PROTOCOLLO://static.DOMINIO/django-static/``.
.. code-block:: yaml
- DJANGO_ALLOWED_ORIGINS=http://static.ilmiosophon.it/django-static/
.. warning::
Ci si assicuri che sia presente uno slash al termine della stringa, oppure il pannello di amministrazione non sarà visualizzato correttamente!
.. seealso::
`STATIC_URL <https://docs.djangoproject.com/en/3.2/ref/settings/#std:setting-STATIC_URL>`_ nella documentazione di Django
``DJANGO_LANGUAGE_CODE``
------------------------
Specifica la lingua che deve usare Sophon nei messaggi di errore.
Usa il formato `language code`_ di Django.
.. code-block:: yaml
- DJANGO_LANGUAGE_CODE=en-us
.. seealso::
`LANGUAGE_CODE <https://docs.djangoproject.com/en/3.2/ref/settings/#language-code>`_ nella documentazione di Django
.. _language code: https://docs.djangoproject.com/en/3.2/topics/i18n/#term-language-code
``DJANGO_TIME_ZONE``
--------------------
Specifica il fuso orario che deve usare Sophon nell'interfaccia di amministrazione.
Usa il formato `tzdata`_.
.. code-block:: yaml
- DJANGO_TIME_ZONE=Europe/Paris
.. hint::
Il fuso orario italiano è ``Europe/Rome``.
.. _tzdata: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
``DJANGO_SU_USERNAME``
----------------------
Specifica il nome del :ref:`superutente` che verrà automaticamente creato qualora il database non contenga altri utenti.
.. code-block:: yaml
- DJANGO_SU_USERNAME=root
``DJANGO_SU_EMAIL``
-------------------
Specifica l'email del :ref:`superutente` che verrà automaticamente creato qualora il database non contenga altri utenti.
.. code-block:: yaml
- DJANGO_SU_USERNAME=bot@steffo.eu
.. note::
Attualmente, l'email non è utilizzata, ma è richiesta da Django per la creazione di un nuovo utente.
``DJANGO_SU_PASSWORD``
----------------------
Specifica la password del :ref:`superutente` che verrà automaticamente creato qualora il database non contenga altri utenti.
.. code-block:: yaml
- DJANGO_SU_PASSWORD=square
.. warning::
La password è un dato estremamente riservato, in quanto chiunque ne venga a conoscenza potrà accedere a Sophon con pieni privilegi!
``REACT_APP_DEFAULT_INSTANCE``
------------------------------
Specifica il valore con cui precompilare il campo "selezione istanza" dell'interfaccia web di Sophon.
Eccetto in configurazioni speciali, deve essere uguale al dominio prefisso dal protocollo e da ``api.``.
.. code-block:: yaml
- REACT_APP_DEFAULT_INSTANCE=https://api.ilmiosophon.it
``APACHE_PROXY_BASE_DOMAIN``
----------------------------
Specifica il dominio che dovrà essere usato come radice per il proxy, ovvero il ``DOMINIO`` per il quale si è configurato il DNS in precedenza.
.. code-block:: yaml
- APACHE_PROXY_BASE_DOMAIN=dev.sophon.steffo.eu
.. seealso::
L'opzione :ref:`\`\`DJANGO_PROXY_BASE_DOMAIN\`\`` più indietro in questa guida, che deve coincidere con questo valore.

View file

@ -0,0 +1,48 @@
Download delle immagini Docker
==============================
Si utilizzi `Docker Compose`_ per scaricare le `immagini`_ Docker necessarie all'avvio di Sophon:
.. code-block:: console
root:/dock/sophon# docker compose pull
[+] Running 4/4
⠿ proxy Pulled 1.5s
⠿ frontend Pulled 1.4s
⠿ db Pulled 1.9s
⠿ backend Pulled 1.6s
Inoltre, si scarichi manualmente l':ref:`immagine del Notebook` che può essere avviata da Sophon:
.. code-block:: console
root:/dock/sophon# docker image pull "ghcr.io/steffo99/sophon-jupyter:latest"
latest: Pulling from steffo99/sophon-jupyter
7b1a6ab2e44d: Already exists
578d7ac380c6: Pull complete
37f1e0b584f6: Pull complete
3c7282703390: Pull complete
b38aa558f711: Pull complete
1412103d568f: Pull complete
67419a9a821e: Pull complete
37e6cc015184: Pull complete
7d9316e2b57c: Pull complete
a7f024508c72: Pull complete
f3eae3c301a1: Pull complete
d3e2107efade: Pull complete
d94bc6f8f069: Pull complete
1e1dc3e818ad: Pull complete
c975ee664182: Pull complete
101cfcc0e15b: Pull complete
bf991a0d7538: Pull complete
4c044af18c7e: Pull complete
605d8c6e8eba: Pull complete
ed06f2ae4a88: Pull complete
ed8b1c841d10: Pull complete
468fe9a390ae: Pull complete
Digest: sha256:5d42e5e40e406130c688914d6a58aa94769eab03620b53e0fd409a7fb2682a01
Status: Downloaded newer image for ghcr.io/steffo99/sophon-jupyter:latest
ghcr.io/steffo99/sophon-jupyter:latest
.. _Docker Compose: https://docs.docker.com/compose/
.. _immagini: https://docs.docker.com/engine/reference/commandline/images/

View file

@ -0,0 +1,22 @@
Avvio di Sophon
===============
Si utilizzi `Docker Compose`_ per eseguire le `immagini`_ di Sophon precedentemente scaricate:
.. code-block:: console
root:/dock/sophon# docker compose up -d
[+] Running 4/4
⠿ Container sophon-db-1 Started 11.3s
⠿ Container sophon-frontend-1 Started 11.7s
⠿ Container sophon-backend-1 Started 10.1s
⠿ Container sophon-proxy-1 Started 11.5s
Si verifichi che i container si siano avviati correttamente con:
.. code-block:: console
root:/dock/sophon# docker compose logs
.. _Docker Compose: https://docs.docker.com/compose/
.. _immagini: https://docs.docker.com/engine/reference/commandline/images/

View file

@ -0,0 +1,62 @@
Configurazione del webserver dell'host
======================================
Si configuri il webserver dell'host per inoltrare tutto il traffico dalla porta 443 (o 80, se si è selezionato ``http`` in :ref:`\`\`DJANGO_PROXY_PROTOCOL\`\``) alla porta locale 30033.
Sono allegate le istruzioni per il webserver `Apache HTTPd`_; possono essere però adattate se si vuole usare un webserver diverso, come `NGINX`_ o `caddy`_.
.. _Apache HTTPd: https://httpd.apache.org/
.. _nginx: https://www.nginx.com/
.. _caddy: https://caddyserver.com/
Con Apache HTTPd
----------------
Ci si assicuri che `mod_rewrite`_, `mod_proxy`_, `mod_proxy_http`_ e `mod_proxy_wstunnel`_ siano attivati.
Si aggiungano i seguenti ``VirtualHost`` alla configurazione:
.. code-block:: apacheconf
<VirtualHost *:80>
ServerName "ilmiosophon.it"
ServerAlias "*.ilmiosophon.it"
RewriteEngine On
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>
.. code-block:: apacheconf
<VirtualHost *:443>
ServerName "ilmiosophon.it"
ServerAlias "*.ilmiosophon.it"
SSLEngine on
SSLCertificateFile "/SOSTITUISCIMI/CON/IL/PERCORSO/ALLA/FULL/CHAIN/SSL"
SSLCertificateKeyFile "/SOSTITUISCIMI/CON/IL/PERCORSO/ALLA/CHIAVE/PRIVATA/SSL"
ProxyPreserveHost On
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://127.0.0.1:30033/$1 [P,L]
RewriteRule /(.*) http://127.0.0.1:30033/$1 [P,L]
Protocols h2 http/1.1
Header always set Strict-Transport-Security "max-age=63072000"
</VirtualHost>
Infine, si riavvii `Apache HTTPd`_:
.. code-block:: console
root:/dock/sophon# systemctl restart httpd
.. _mod_rewrite: https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html
.. _mod_proxy: https://httpd.apache.org/docs/2.4/mod/mod_proxy.html
.. _mod_proxy_http: https://httpd.apache.org/docs/2.4/mod/mod_proxy_http.html
.. _mod_proxy_wstunnel: https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html

View file

@ -0,0 +1,4 @@
Verificare il funzionamento
===========================
Se tutto è stato configurato correttamente, l'interfaccia web Sophon dovrebbe essere raggiungibile al dominio selezionato (``https://ilmiosophon.it``), e dovrebbe essere possibile effettuare il login con le credenziali configurate del primo :ref:`superutente`.

View file

@ -0,0 +1,18 @@
Installazione
*************
Questo capitolo fornisce le informazioni per l'installazione di Sophon su un server Linux.
.. toctree::
:numbered:
:maxdepth: 1
1_requirements
2_preparing_compose
3_configuring_dns
4_configuring_compose
5_pulling_images
6_starting_sophon
7_host_reverse_proxy
8_final_check

View file

@ -0,0 +1,32 @@
Pannello di amministrazione
===========================
Sophon include un pannello di amministrazione, accessibile premendo *Go to the admin page* sulla schermata di login, oppure visitando l'URL ``api.DOMINIO/admin``.
.. image:: admin_where.png
Effettuare l'accesso
--------------------
Per utilizzare il pannello di amministrazione è necessario inserire le credenziali di un :ref:`superutente`.
.. image:: admin_login.png
La schermata principale
-----------------------
Nella schermata principale del pannello di amministrazione è visibile l'elenco di tutti i tipi di entità gestite da Django, assieme ad uno storico delle ultime operazioni effettuate dal pannello su di esse.
.. image:: admin_home.png
È possibile cliccare sul collegamento *Add* di fianco ad un tipo di entità per **crearne** una nuova di quel tipo, oppure il collegamento *Change* per **visualizzare**, **modificare** ed **eliminare** tutte le entità già esistenti di quel tipo.
La barra del titolo
-------------------
Tutte le pagine includono in cima la **barra del titolo**, che permette al :ref:`superutente` attualmente collegato di **cambiare la propria password** o effettuare la **disconnessione** dal pannello.
.. image:: topright.png

View file

@ -0,0 +1,112 @@
Tipi di risorse
===============
Tokens
------
Contiene l'elenco di tutti i token di sessione usati per l'autenticazione tra l'API e l'interfaccia web di Sophon.
È possibile modificarli per **cambiare l'utente connesso** ad una certa sessione, oppure eliminarli per **forzare la disconnessione** di determinate sessioni.
.. note::
In seguito ad una disconnessione forzata, l'utente riscontrerà errori "non autorizzato" sull'interfaccia web fino ad un aggiornamento della pagina o logout manuale.
.. image:: token_list.png
:scale: 50%
.. image:: token_detail.png
:scale: 50%
Users
-----
Contiene l'elenco di tutti gli utenti registrati su Sophon.
In questa pagina è possibile la :ref:`creazione di nuovi utenti`, così come il **cambio di password**, l'**assegnazione di privilegi** di :ref:`superutente` e la **disattivazione degli utenti**.
.. note::
I superutenti devono avere sia *staff status* sia *superuser status* attivi per poter utilizzare il pannello di amministrazione.
.. image:: user_list.png
:scale: 50%
.. image:: user_detail.png
:scale: 50%
Research groups
---------------
Contiene l'elenco di tutti i gruppi di ricerca creati su Sophon.
Dal pannello di amministrazione è possibile effettuare modifiche ed eliminazioni **ignorando i permessi normalmente richiesti** per farlo e **trasferire la proprietà** di un gruppo da un utente all'altro.
.. image:: researchgroup_list.png
:scale: 50%
.. image:: researchgroup_detail.png
:scale: 50%
Sophon instance details
-----------------------
Contiene un'entità speciale che controlla l'**aspetto** dell':ref:`istanza`.
Modificandola, è possibile personalizzare:
- il **nome** dell':ref:`istanza`, che verrà visualizzato come titolo dell'interfaccia web;
.. image:: custom_title.png
- la **descrizione** dell':ref:`istanza`, visualizzata all'interno del riquadro "A proposito dell'istanza";
.. image:: custom_description.png
- il **tema colori** dell':ref:`istanza`, applicato all'interfaccia web una volta che un':ref:`istanza` è stata selezionata.
.. image:: theme_sophon.png
:width: 240
.. image:: theme_royalblue.png
:width: 240
.. image:: theme_amber.png
:width: 240
.. image:: theme_paper.png
:width: 240
.. image:: theme_hacker.png
:width: 240
Notebooks
---------
Contiene l'elenco di tutti i :ref:`notebook` creati su Sophon.
Oltre ad alterare le entità **ignorando i permessi**, è possibile vedere alcuni parametri tecnici, come l'ID del container Docker a cui è associato il notebook, oppure la porta o l'URL a cui è accessibile il notebook dal proxy.
.. warning::
Modificare *slug*, *container ID*, *local port number* o *internal URL* mentre il :ref:`notebook` è avviato renderà potenzialmente la connessione e l'arresto del notebook!
.. image:: notebook_list.png
:scale: 50%
.. image:: notebook_detail.png
:scale: 50%
Research projects
-----------------
Contiene l'elenco di tutti i progetti di ricerca creati su Sophon.
Oltre ad alterare le entità **ignorando i permessi**, è possibile **trasferire un progetto** da un gruppo a un altro.
.. image:: researchproject_list.png
:scale: 50%
.. image:: researchproject_detail.png
:scale: 50%

BIN
report/source/2_admin/2_administration/admin_home.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/2_admin/2_administration/admin_login.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/2_admin/2_administration/admin_where.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
report/source/2_admin/2_administration/custom_title.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/2_admin/2_administration/customization.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,9 @@
Amministrazione
***************
Questo capitolo fornisce informazioni su come amministrare un':ref:`istanza` Sophon.
.. toctree::
1_admin_panel
2_entities

BIN
report/source/2_admin/2_administration/notebook_detail.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/2_admin/2_administration/notebook_list.png (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
report/source/2_admin/2_administration/theme_amber.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/2_admin/2_administration/theme_hacker.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/2_admin/2_administration/theme_paper.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/2_admin/2_administration/theme_royalblue.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/2_admin/2_administration/theme_sophon.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/2_admin/2_administration/token_detail.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/2_admin/2_administration/token_list.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/2_admin/2_administration/topright.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/2_admin/2_administration/user_detail.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/2_admin/2_administration/user_list.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,21 @@
Aggiornamento
*************
Per aggiornare Sophon, è sufficiente usare `Docker Compose`_ per scaricare le immagini aggiornate e riavviare i container del software.
.. code-block:: console
root:/dock/sophon# docker compose down
root:/dock/sophon# docker compose pull
root:/dock/sophon# docker compose up -d
.. warning::
In seguito ad un aggiornamento o un riavvio, alcuni Notebook potrebbero essere **irraggiungibili dal proxy**.
In tal caso, sarà sufficiente **fermarli** e **riavviarli** dall'interfaccia web.
Non si verificherà alcuna perdita di dati!
.. _Docker Compose: https://docs.docker.com/compose/

View file

@ -0,0 +1,27 @@
Disinstallazione
****************
Per rimuovere completamente Sophon, è necessario innanzitutto arrestare i container del software principale:
.. code-block:: console
root:/dock/sophon# docker compose down
In seguito, è necessario arrestare tutti i container dei notebook ancora avviati:
.. code-block:: console
root:/dock/sophon# docker container ls
c160ea085fe1 steffo45/jupyterlab-docker-sophon "tini -g -- start-no…" 23 hours ago Up 23 hours sophon-container-my-first-notebook
0892874ea0d5 ghcr.io/steffo99/sophon-jupyter "tini -g -- start-no…" 3 minutes ago Up 3 minutes (healthy) sophon-container-normal-slug
root:/dock/sophon# docker container rm --force c160ea085fe1 0892874ea0d5
Infine sarà possibile liberare lo spazio occupato dalle risorse Docker di Sophon:
.. code-block:: console
root:/dock/sophon# docker compose down -v
root:/dock/sophon# docker volume prune
root:/dock/sophon# docker container prune
root:/dock/sophon# docker network prune
root:/dock/sophon# docker image prune

View file

@ -0,0 +1,40 @@
Strumenti usati per lo sviluppo
*******************************
Per sviluppare Sophon sono usati i seguenti strumenti:
- `IntelliJ IDEA Ultimate`_, un IDE multilinguaggio, con i seguenti plugin:
- Python
- Poetry
- ReStructuredText
- Node.JS
- JavaScript and TypeScript
- CSS
- Git
- Docker
- `Git`_, uno strumento di controllo versione;
- `GitHub`_, un host per repository `Git`_;
- `GitHub Issues`_, un issue tracker integrato in `GitHub`_;
- `GitHub Actions`_, un sistema di `Continuous Integration`_ e `Continuous Deployment`_ integrato in `GitHub`_;
- `GitHub Containers`_, un registro di container Docker integrato in `GitHub`_;
- `CodeQL`_, un tool di analisi statica integrato in `GitHub`_;
- `Dependabot`_, un tool di analisi delle dipendenze integrato in `GitHub`_;
- `Sphinx`_, uno strumento per la creazione di documentazione.
.. _IntelliJ IDEA Ultimate: https://www.jetbrains.com/idea/
.. _Git: https://git-scm.com/
.. _GitHub: https://github.com/
.. _GitHub Issues: https://github.com/features/issues/
.. _GitHub Actions: https://github.com/features/actions
.. _Continuous Integration: https://it.wikipedia.org/wiki/Integrazione_continua
.. _Continuous Deployment: https://en.wikipedia.org/wiki/Continuous_deployment
.. _CodeQL: https://codeql.github.com/
.. _GitHub Containers: https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry
.. _Sphinx: https://www.sphinx-doc.org/
.. _Dependabot: https://dependabot.com/
.. seealso::
Nel capitolo successivo sono descritte le tecnologie utilizzate all'interno di Sophon.

View file

@ -0,0 +1,16 @@
Librerie e tecnologie utilizzate
--------------------------------
.. note::
Sono elencate solo le principali librerie utilizzate; dipendenze e librerie minori non sono specificate, ma sono visibili all'interno del file ``poetry.lock``.
- Il linguaggio di programmazione `Python <https://www.python.org/>`_
- Il gestore di dipendenze `Poetry <https://python-poetry.org/>`_
- Il framework web `Django <https://www.djangoproject.com/>`_
- L'estensione per Django `Django REST Framework <https://www.django-rest-framework.org/>`_
- L'estensione per Django `Django CORS Headers <https://github.com/adamchainz/django-cors-headers>`_
- L'adattatore database per PostgreSQL `Psycopg <https://pypi.org/project/psycopg2/>`_
- Il `Docker SDK for Python <https://docker-py.readthedocs.io/en/stable/>`_
- Il server web `Gunicorn <https://gunicorn.org/>`_
- L'utilità `lazy-object-proxy <https://github.com/ionelmc/python-lazy-object-proxy>`_

View file

@ -0,0 +1,89 @@
Il progetto sophon
------------------
.. default-domain:: py
.. default-role:: obj
.. module:: sophon
Il progetto Django Sophon aggiunge varie funzionalità al template base dei progetti Django.
Pagina di amministrazione personalizzata
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. module:: sophon.admin
La pagina di amministrazione viene personalizzata con la classe `SophonAdminSite`, che modifica alcuni parametri della classe base.
Inoltre, il template predefinito viene sovrascritto da quello all'interno del file ``templates/admin/base.html``, che sostituisce il foglio di stile con uno personalizzato per Sophon.
.. class:: SophonAdminSite(django.contrib.admin.AdminSite)
.. attribute:: site_header = "Sophon Server Administration"
Il nome della pagina nell'header viene modificato a *Sophon Server Administration*.
.. attribute:: site_title = "Sophon Server Administration"
Il titolo della pagina nell'header viene anch'esso modificato a *Sophon Server Administration*.
.. attribute:: site_url = None
Il collegamento *View Site* viene rimosso, in quanto è possibile accedere all'interfaccia web di Sophon da più domini contemporaneamente.
.. attribute:: index_title = "Resources Administration"
Il titolo dell'indice viene modificato a *Resources Administration*.
.. class:: SophonAdminConfig(django.contrib.admin.apps.AdminConfig)
.. attribute:: default_site = "sophon.admin.SophonAdminSite"
`.SophonAdminSite` è selezionata come classe predefinita per il sito di amministrazione.
Impostazioni dinamiche
^^^^^^^^^^^^^^^^^^^^^^
.. module:: sophon.settings
Il file di impostazioni viene modificato per **permettere la configurazione attraverso variabili di ambiente** invece che attraverso il file ``settings.py``, rendendo il deployment con Docker molto più semplice.
.. code-block:: python
try:
DATABASE_ENGINE = os.environ["DJANGO_DATABASE_ENGINE"]
except KeyError:
log.warning("DJANGO_DATABASE_ENGINE was not set, defaulting to PostgreSQL")
DATABASE_ENGINE = "django.db.backends.postgresql"
log.debug(f"{DATABASE_ENGINE = }")
Inoltre, viene configurato il modulo `logging` per emettere testo colorato di più facile comprensione usando il package `coloredlogs`.
.. code-block:: python
"detail": {
"()": coloredlogs.ColoredFormatter,
"format": "{asctime:>19} | {name:<24} | {levelname:>8} | {message}",
"style": "{",
}
Autenticazione migliorata
^^^^^^^^^^^^^^^^^^^^^^^^^
.. module:: sophon.auth1
La classe `rest_framework.authentication.TokenAuthentication` viene modificata per ottenere un comportamento conforme agli standard del web.
.. class:: BearerTokenAuthentication(rest_framework.authentication.TokenAuthentication)
.. attribute:: keyword = "Bearer"
Si configura `rest_framework` per accettare header di autenticazione nella forma ``Bearer <token>``, invece che ``Token <token>``.
.. module:: sophon.auth2
La view `rest_framework.authtoken.views.ObtainAuthToken` viene estesa per aggiungere dati alla risposta di autenticazione riuscita.
.. class:: CustomObtainAuthToken(rest_framework.authtoken.views.ObtainAuthToken)
.. method:: post(self, request, *args, **kwargs)
In particolare, viene aggiunta una chiave ``user``, che contiene i dettagli sull'utente che ha effettuato il login.

View file

@ -0,0 +1,333 @@
L'app sophon.core
-----------------
.. default-domain:: py
.. default-role:: obj
.. module:: sophon.core
L'app `sophon.core` è l'app principale del progetto, e non può essere disattivata, in quanto dipendenza obbligatoria di tutte le altre app.
Aggiunta di un nuovo comando di gestione
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. module:: sophon.core.management.commands.initsuperuser
Per permettere l'integrazione la creazione automatica del primo :ref:`superutente` quando Sophon viene eseguito da Docker, viene introdotto dall'app il comando di gestione ``initsuperuser``.
.. class:: Command
Questo comando crea automaticamente un :ref:`superutente` con le credenziali specificate in :ref:`\`\`DJANGO_SU_USERNAME\`\``, :ref:`\`\`DJANGO_SU_EMAIL\`\`` e :ref:`\`\`DJANGO_SU_PASSWORD\`\``.
Modello base astratto
^^^^^^^^^^^^^^^^^^^^^
.. module:: sophon.core.models
Viene estesa la classe astratta `django.db.models.Model` con funzioni per stabilire il livello di accesso di un utente all'oggetto e per generare automaticamente i `rest_framework.serializers.ModelSerializer` in base al livello di accesso.
.. class:: SophonModel(django.db.models.Model)
.. method:: can_edit(self, user: django.contrib.auth.models.User) -> bool
:abstractmethod:
Controlla se un utente può modificare l'oggetto attuale.
:param user: L'utente da controllare.
:returns: `True` se l'utente deve poter modificare l'oggetto, altrimenti `False`.
.. method:: can_admin(self, user: django.contrib.auth.models.User) -> bool
:abstractmethod:
Controlla se un utente può amministrare l'oggetto attuale.
:param user: L'utente da controllare.
:returns: `True` se l'utente deve poter amministrare l'oggetto, altrimenti `False`.
.. classmethod:: get_fields(cls) -> set[str]
:returns: il `set` di nomi di campi che devono essere mostrati quando viene richiesto l'oggetto attraverso l'API.
.. classmethod:: get_editable_fields(cls) -> set[str]
:returns: il `set` di nomi di campi di cui deve essere permessa la modifica se l'utente può modificare (`.can_edit`) l'oggetto.
.. classmethod:: get_administrable_fields(cls) -> set[str]
:returns: il `set` di nomi di campi di cui deve essere permessa la modifica se l'utente può amministrare (`.can_admin`) l'oggetto.
.. classmethod:: get_creation_fields(cls) -> set[str]
:returns: il `set` di nomi di campi che possono essere specificati dall'utente al momento della creazione dell'oggetto.
Modello di autorizzazione astratto
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Viene definito un nuovo modello astratto, basato su `SophonModel`, che permette di determinare i permessi dell'utente in base alla sua appartenenza al gruppo a cui è collegato l'oggetto implementatore.
.. class:: SophonGroupModel(SophonModel)
.. method:: get_group(self) -> ResearchGroup
:abstractmethod:
:returns: Il gruppo a cui appartiene l'oggetto.
.. classmethod:: get_access_to_edit(cls) -> sophon.core.enums.SophonGroupAccess
:returns: Il livello di autorità all'interno del gruppo necessario per modificare l'oggetto.
.. classmethod:: get_access_to_admin(cls) -> sophon.core.enums.SophonGroupAccess
:returns: Il livello di autorità all'interno del gruppo necessario per amministrare l'oggetto.
.. method:: get_access_serializer(self, user: User) -> typing.Type[rest_framework.serializers.ModelSerializer]
:returns: Restituisce il `rest_framework.serializers.ModelSerializer` adeguato al livello di autorità dell'utente.
.. class:: sophon.core.enums.SophonGroupAccess(enum.IntEnum)
Enumerazione che stabilisce il livello di autorità che un utente può avere all'interno di un gruppo.
.. attribute:: NONE = 0
Utente :ref:`ospite`.
.. attribute:: REGISTERED = 10
:ref:`Utente` registrato.
.. attribute:: MEMBER = 50
Membro del :ref:`gruppo di ricerca`.
.. attribute:: OWNER = 100
Creatore del :ref:`gruppo di ricerca`.
.. attribute:: SUPERUSER = 200
:ref:`Superutente` con privilegi universali.
Modello dei dettagli dell'istanza
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Viene creato il modello che rappresenta i dettagli dell':ref:`istanza` Sophon.
.. class:: SophonInstanceDetails(SophonModel)
.. attribute:: id: IntegerField [1]
Impostando ``1`` come unica scelta per il campo della chiave primaria ``id``, si crea un modello "singleton", ovvero un modello di cui può esistere un'istanza sola in tutto il database.
L'istanza unica viene creata dalla migrazione ``0004_sophoninstancedetails.py``.
.. attribute:: name: CharField
.. attribute:: description: TextField
.. attribute:: theme: CharField ["sophon", "paper", "royalblue", "hacker", "amber"]
.. method:: version: str
:property:
:returns: La versione installata del pacchetto `sophon`.
.. seealso::
:ref:`Sophon instance details` nella guida per l'amministratore.
Modello del gruppo di ricerca
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Viene creato il modello che rappresenta un :ref:`gruppo di ricerca`.
.. class:: ResearchGroup(SophonGroupModel)
.. attribute:: slug: SlugField
.. attribute:: name: CharField
.. attribute:: description: TextField
.. attribute:: members: ManyToManyField → django.contrib.auth.models.User
.. attribute:: owner: ForeignKey → django.contrib.auth.models.User
.. attribute:: access: CharField ["MANUAL", "OPEN"]
Estensione ai permessi di Django
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. module:: sophon.core.permissions
I permessi di `rest_framework` vengono estesi con due nuove classi che utilizzano il :ref:`modello di autorizzazione` precedentemente definito.
.. class:: Edit(rest_framework.permissions.BasePermission)
Consente l'interazione solo agli utenti che possono modificare (`.can_edit`) l'oggetto.
.. class:: Admin(rest_framework.permissions.BasePermission)
Consente l'interazione solo agli utenti che possono amministrare (`.can_admin`) l'oggetto.
Viewset astratti
^^^^^^^^^^^^^^^^
.. module:: sophon.core.views
Vengono definiti tre viewset in grado di utilizzare i metodi aggiunti dalle classi astratte `.models.SophonModel` e `.models.SophonGroupModel`.
.. class:: ReadSophonViewSet(rest_framework.viewsets.ReadOnlyModelViewSet, metaclass=abc.ABCMeta)
Classe **astratta** che estende la classe base `rest_framework.viewsets.ReadOnlyModelViewSet` con metodi di utilità mancanti nell'implementazione originale, allacciandola inoltre a `.models.SophonGroupModel`.
.. method:: get_queryset(self) -> QuerySet
:abstractmethod:
Imposta come astratto (e quindi obbligatorio) il metodo `rest_framework.viewsets.ReadOnlyModelViewSet.get_queryset`.
.. method:: permission_classes(self)
:property:
Sovrascrive il campo di classe `rest_framework.viewsets.ReadOnlyModelViewSet.permission_classes` con una funzione, permettendone la selezione dei permessi richiesti al momento di ricezione di una richiesta HTTP (invece che al momento di definizione della classe).
Delega la selezione delle classi a `.get_permission_classes`.
.. method:: get_permission_classes(self) -> typing.Collection[typing.Type[permissions.BasePermission]]
Funzione che permette la selezione dei permessi necessari per effetuare una determinata richiesta al momento di ricezione di quest'ultima.
Utile per le classi che erediteranno da questa.
.. method:: get_serializer_class(self) -> typing.Type[Serializer]
Funzione che permette la selezione del `rest_framework.serializers.Serializer` da utilizzare per una determinata richiesta al momento di ricezione di quest'ultima.
Utilizza:
- il serializzatore **in sola lettura** per elencare gli oggetti (azione ``list``);
- il serializzatore **di creazione** per creare nuovi oggetti (azione ``create``) e per generare i metadati del viewset (azione ``metadata``);
- il serializzatore ottenuto da `.models.SophonGroupModel.get_access_serializer` per la visualizzazione dettagliata (azione ``retrieve``), la modifica (azioni ``update`` e ``partial_update``) e l'eliminazione (azione ``destroy``) di un singolo oggetto;
- il serializzatore ottenuto da `.get_custom_serializer_classes` per le azioni personalizzate.
.. seealso::
`.models.SophonGroupModel`
.. method:: get_custom_serializer_classes(self) -> t.Type[Serializer]
Permette alle classi che ereditano da questa di selezionare quale `rest_framework.serializers.Serializer` utilizzare per le azioni personalizzate.
.. class:: WriteSophonViewSet(rest_framework.viewsets.ModelViewSet, ReadSophonViewSet, metaclass=abc.ABCMeta)
Classe **astratta** che estende la classe base `ReadSophonViewSet` aggiungendoci i metodi di `rest_framework.viewsets.ModelViewSet` che effettuano modifiche sugli oggetti.
Depreca i metodi ``perform_*`` di `rest_framework`, introducendone versioni migliorate con una signature diversa dal nome di ``hook_*``.
.. method:: perform_create(self, serializer)
.. deprecated:: 0.1
.. method:: perform_update(self, serializer)
.. deprecated:: 0.1
.. method:: perform_destroy(self, serializer)
.. deprecated:: 0.1
.. method:: hook_create(self, serializer) -> dict[str, typing.Any]
Funzione chiamata durante l'esecuzione dell'azione di creazione oggetto ``create``.
:param serializer: Il `~rest_framework.serializers.Serializer` già "riempito" contenente i dati dell'oggetto che sta per essere creato.
:raises .HTTPException: È possibile interrompere la creazione dell'oggetto con uno specifico codice errore sollevando una `.HTTPException` all'interno della funzione.
:returns: Un `dict` da unire a quello del `~rest_framework.serializers.Serializer` per formare l'oggetto da creare.
.. method:: hook_update(self, serializer) -> dict[str, t.Any]
Funzione chiamata durante l'esecuzione delle azioni di modifica oggetto ``update`` e ``partial_update``.
:param serializer: Il `~rest_framework.serializers.Serializer` già "riempito" contenente i dati dell'oggetto che sta per essere modificato.
:raises .HTTPException: È possibile interrompere la creazione dell'oggetto con uno specifico codice errore sollevando una `.HTTPException` all'interno della funzione.
:returns: Un `dict` da unire a quello del `~rest_framework.serializers.Serializer` per formare l'oggetto da modificare.
.. method:: hook_destroy(self, serializer) -> dict[str, typing.Any]
Funzione chiamata durante l'esecuzione dell'azione di eliminazione oggetto ``destroy``.
:raises .HTTPException: È possibile interrompere la creazione dell'oggetto con uno specifico codice errore sollevando una `.HTTPException` all'interno della funzione.
.. exception:: sophon.core.errors.HTTPException
Tipo di eccezione che è possibile sollevare nei metodi ``hook_*`` di `.WriteSophonViewSet` per interrompere l'azione in corso senza applicare le modifiche.
.. attribute:: status: int
Permette di specificare il codice errore con cui rispondere alla richiesta interrotta.
.. class:: SophonGroupViewSet(WriteSophonViewSet, metaclass=abc.ABCMeta)
Classe **astratta** che estende la classe base `.WriteSophonViewSet` estendendo gli ``hook_*`` con verifiche dei permessi dell'utente che tenta di effettuare l'azione.
.. method:: get_group_from_serializer(self, serializer) -> models.ResearchGroup
:abstractmethod:
Metodo necessario a trovare il gruppo a cui apparterrà un oggetto prima che il suo serializzatore venga elaborato.
:param serializer: Il `~rest_framework.serializers.Serializer` già "riempito" contenente i dati dell'oggetto.
Viewset concreti
^^^^^^^^^^^^^^^^
Vengono poi definiti tre viewset e una view che permettono interazioni tra l'utente e i modelli definiti nell'app.
.. class:: UsersByIdViewSet(ReadSophonViewSet)
Viewset in sola lettura che permette di recuperare gli utenti dell'istanza partendo dal loro ``id``.
Accessibile all'URL :samp:`/api/core/users/by-id/{ID}/`.
.. class:: UsersByUsernameViewSet(ReadSophonViewSet)
Viewset in sola lettura che permette di recuperare gli utenti dell'istanza partendo dal loro ``username``.
Accessibile all'URL :samp:`/api/core/users/by-username/{USERNAME}/`.
.. class:: ResearchGroupViewSet(WriteSophonViewSet)
Viewset in lettura e scrittura che permette di interagire con i gruppi di ricerca.
Accessibile all'URL :samp:`/api/core/groups/{GROUP_SLUG}/`.
.. method:: join(self, request: Request, pk: int) -> Response
Azione personalizzata che permette ad un utente di unirsi ad un gruppo aperto.
Utilizza `.models.SophonGroupModel.get_access_serializer`.
.. method:: leave(self, request: Request, pk: int) -> Response
Azione personalizzata che permette ad un utente di abbandonare un gruppo di cui non è proprietario.
Utilizza `.models.SophonGroupModel.get_access_serializer`.
.. class:: SophonInstanceDetailsView(APIView)
View che restituisce il valore attuale dell'unico oggetto `.models.SophonInstanceDetails`.
Accessibile tramite richieste ``GET`` all'URL :samp:`/api/core/instance/`.
Pagina di amministrazione
^^^^^^^^^^^^^^^^^^^^^^^^^
.. module:: sophon.core.admin
Vengono infine registrati nella pagina di amministrazione i modelli concreti definiti in questa app, effettuando alcune personalizzazioni elencate in seguito.
.. class:: ResearchGroupAdmin(SophonAdmin)
Per i gruppi di ricerca, viene specificato un ordinamento, permesso il filtraggio e selezionati i campi più importanti da visualizzare nella lista.
.. class:: SophonInstanceDetails(SophonAdmin)
Per i dettagli dell'istanza, vengono disattivate tutte le azioni, impedendo la creazione o eliminazione del singleton.

View file

@ -0,0 +1,62 @@
L'app sophon.projects
-----------------------
.. default-domain:: py
.. default-role:: obj
.. module:: sophon.projects
L'app `sophon.projects` è un app secondaria che dipende da `sophon.core` che introduce in Sophon il concetto di :ref:`progetto di ricerca`.
.. caution::
Anche se l'app `sophon.projects` è opzionale (il progetto può funzionare senza di essa), si sconsiglia di disattivarla, in quanto il :ref:`modulo frontend` si aspetta che l'app sia attiva e solleverà un errore nel caso che i viewset forniti da questa app non siano disponibile.
Modello del progetto di ricerca
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. module:: sophon.projects.models
Viene introdotto un modello concreto che rappresenta un :ref:`progetto di ricerca`.
.. class:: ResearchProject(SophonGroupModel)
.. attribute:: slug: SlugField
.. attribute:: group: ForeignKey → sophon.core.models.ResearchGroup
.. attribute:: name: CharField
.. attribute:: description: TextField
.. attribute:: visibility: CharField ["PUBLIC", "INTERNAL", "PRIVATE"]
Viewset del gruppo di ricerca
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. module:: sophon.projects.views
Da una base comune, vengono creati due viewset per interagire con i progetti di ricerca.
.. class:: ResearchProjectViewSet(SophonGroupViewSet, metaclass=abc.ABCMeta)
Classe **astratta** che effettua l'override di `~sophon.core.views.SophonGroupView.get_group_from_serializer` per entrambi i viewset che seguono.
.. class:: ResearchProjectsBySlugViewSet(ResearchProjectViewSet)
Viewset in lettura e scrittura che permette di interagire con tutti i progetti di ricerca a cui l'utente loggato ha accesso.
Accessibile all'URL :samp:`/api/projects/by-slug/{PROJECT_SLUG}/`.
.. class:: ResearchProjectsByGroupViewSet(ResearchProjectViewSet)
Viewset in lettura e scrittura che permette di interagire con i progetti di ricerca a cui l'utente loggato ha accesso, filtrati per il gruppo a cui appartengono.
Il filtraggio viene effettuato limitando il queryset.
Accessibile all'URL :samp:`/api/projects/by-group/{GROUP_SLUG}/{PROJECT_SLUG}/`.
Amministrazione del gruppo di ricerca
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. module:: sophon.projects.admin
Il modello `.models.ResearchProject` viene registrato nella pagina di amministrazione attraverso la seguente classe:
.. class:: ResearchProjectAdmin(sophon.core.admin.SophonAdmin)
Classe per la pagina di amministrazione che specifica un ordinamento, permette il filtraggio per gruppo di appartenenza e visibilità, e specifica i campi da visualizzare nell'elenco dei progetti.

View file

@ -0,0 +1,241 @@
L'app sophon.notebooks
----------------------
.. default-domain:: py
.. default-role:: obj
.. module:: sophon.notebooks
L'app `sophon.notebooks` è un app secondaria che dipende da `sophon.projects` che introduce in Sophon il concetto di :ref:`notebook`.
.. caution::
Anche se l'app `sophon.notebooks` è opzionale (il progetto può funzionare senza di essa), si sconsiglia di disattivarla, in quanto il :ref:`modulo frontend` si aspetta che l'app sia attiva e solleverà un errore nel caso che i viewset forniti da questa app non siano disponibile.
Funzionamento di un notebook
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Internamente, un notebook non è altro che un container Docker accessibile ad un determinato indirizzo il cui stato è sincronizzato con un oggetto del database del :ref:`modulo backend`.
Modalità sviluppo
"""""""""""""""""
Per facilitare lo sviluppo di Sophon, sono previste due modalità di operazione di quest'ultimo:
- nella prima, la **modalità sviluppo**, il :ref:`modulo proxy` non è in esecuzione, ed è possibile collegarsi direttamente ai container attraverso collegamenti a ``localhost``;
- nella seconda, la **modalità produzione**, il :ref:`modulo proxy` è in esecuzione all'interno di un container Docker, e si collega agli altri container attraverso i rispettivi network Docker agli indirizzi comunicatogli dal :ref:`modulo backend`.
.. image:: notebooks_diagram.png
Gestione della rubrica del proxy
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. module:: sophon.notebooks.apache
Viene creata una classe per la gestione della rubrica del proxy, utilizzando il modulo `dbm.gnu`, supportato da HTTPd.
La rubrica mappa gli URL pubblici dei notebook a URL privati relativi al :ref:`modulo proxy`, in modo da effettuare reverse proxying **dinamico**.
.. class:: ApacheDB
Classe che permette il recupero, la creazione, la modifica e l'eliminazioni di chiavi di un database `dbm.gnu` come se quest'ultimo fosse un `dict` con supporto a chiavi e valori `str` e `bytes`.
.. staticmethod:: convert_to_bytes(item: typing.Union[str, bytes]) -> bytes
Tutte le `str` passate a questa classe vengono convertite in `bytes` attraverso questa funzione, che effettua un encoding in ASCII e solleva un errore se quest'ultimo fallisce.
Assegnazione porta effimera
^^^^^^^^^^^^^^^^^^^^^^^^^^^
In *modalità sviluppo*, è necessario trovare una porta libera a cui rendere accessibile i container Docker dei notebook.
.. function:: get_ephemeral_port() -> int
Questa funzione apre e chiude immediatamente un `socket.socket` all'indirizzo ``localhost:0`` in modo da ricevere dal sistema operativo un numero di porta sicuramente libero.
Connessione al daemon Docker
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. module:: sophon.notebooks.docker
Per facilitare l'utilizzo del daemon Docker per la gestione dei container dei notebook, viene utilizzato il modulo `docker`.
.. function:: get_docker_client() -> docker.DockerClient
Funzione che crea un client Docker con le variabili di ambiente del modulo.
.. data:: client: docker.DockerClient = lazy_object_proxy.Proxy(get_docker_client)
Viene creato un client Docker globale con inizializzazione lazy al fine di non tentare connessioni (lente!) al daemon quando non sono necessarie.
Controllo dello stato di salute
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Il modulo `docker` viene esteso implementando supporto per l'istruzione ``HEALTHCHECK`` dei ``Dockerfile``.
.. class:: HealthState(enum.IntEnum)
Enumerazione che elenca gli stati possibili in cui può essere la salute di un container.
.. attribute:: UNDEFINED = -2
Il ``Dockerfile`` non ha un ``HEALTHCHECK`` definito.
.. attribute:: STARTING = -1
Il container Docker non mai completato con successo un ``HEALTHCHECK``.
.. attribute:: HEALTHY = 0
Il container Docker ha completato con successo l'ultimo ``HEALTHCHECK`` e quindi sta funzionando correttamente.
.. attribute:: UNHEALTHY = 1
Il container Docker ha fallito l'ultimo ``HEALTHCHECK``.
.. function:: get_health(container: docker.models.containers.Container) -> HealthState
Funzione che utilizza l'API a basso livello del client Docker per recuperare l'`HealthState` dei container.
.. function:: sleep_until_container_has_started(container: docker.models.containers.Container) -> HealthState
Funzione bloccante che restituisce solo quando lo stato del container specificato non è `HealthState.STARTING`.
Generazione di token sicuri
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Si è scelto di rendere completamente trasparente all'utente il meccanismo di autenticazione a JupyterLab.
Pertanto, si è verificata la necessità di generare token crittograficamente sicuri da richiedere per l'accesso a JupyterLab.
.. function:: generate_secure_token() -> str
Funzione che utilizza `secrets.token_urlsafe` per generare un token valido e crittograficamente sicuro.
Modello dei notebook
^^^^^^^^^^^^^^^^^^^^
.. module:: sophon.notebooks.models
Viene definito il modello rappresentante un :ref:`notebook`.
.. class:: Notebook(SophonGroupModel)
.. attribute:: slug: SlugField
Lo slug dei notebook prevede ulteriori restrizioni oltre a quelle previste dallo `django.db.models.SlugField`:
- non può essere uno dei seguenti valori: ``api``, ``static``, ``proxy``, ``backend``, ``frontend``, ``src``;
- non può iniziare o finire con un trattino ``-``.
.. attribute:: project: ForeignKey → sophon.projects.models.ResearchProject
.. attribute:: name: CharField
.. attribute:: locked_by: ForeignKey → django.contrib.auth.models.User
.. attribute:: container_image: CharField ["ghcr.io/steffo99/sophon-jupyter"]
Campo che specifica l'immagine che il client Docker dovrà avviare per questo notebook.
Al momento ne è configurata una sola per semplificare l'esperienza utente, ma altre possono essere specificate per permettere agli utenti più scelta.
.. note::
Al momento, le immagini specificate devono esporre un server web sulla porta ``8888``, e supportare il protocollo di connessione di Jupyter, ovvero :samp:`{PROTOCOLLO}://immagine:8888/lab?token={TOKEN}` e :samp:`{PROTOCOLLO}://immagine:8888/tree?token={TOKEN}`.
.. attribute:: jupyter_token: CharField
Il token segreto che verrà passato attraverso le variabili di ambiente al container Docker dell'oggetto per permettere solo agli utenti autorizzati di accedere a quest'ultimo.
.. attribute:: container_id: CharField
L'id assegnato dal daemon Docker al container di questo oggetto.
Se il notebook non è avviato, questo attributo varrà `None`.
.. attribute:: port: IntegerField
La porta assegnata al container Docker dell'oggetto nel caso in cui Sophon sia avviato in "modalità sviluppo", ovvero con il :ref:`modulo proxy` in esecuzione sul sistema host.
.. attribute:: internal_url: CharField
L'URL a cui è accessibile il container Docker dell'oggetto nel caso in cui Sophon non sia avviato in "modalità sviluppo", ovvero con il :ref:`modulo proxy` in esecuzione all'interno di un container.
.. method:: log(self) -> logging.Logger
:property:
Viene creato un `logging.Logger` per ogni oggetto della classe, in modo da facilitare il debug relativo ad uno specifico notebook.
Il nome del logger ha la forma :samp:`sophon.notebooks.models.Notebook.{NOTEBOOK_SLUG}`.
.. method:: enable_proxying(self) -> None
Aggiunge l'indirizzo del notebook alla rubrica del proxy.
.. method:: disable_proxying(self) -> None
Rimuove l'indirizzo del notebook dalla rubrica del proxy.
.. method:: sync_container(self) -> t.Optional[docker.models.containers.Container]
Sincronizza lo stato dell'oggetto nel database con lo stato del container Docker nel sistema.
.. method:: create_container(self) -> docker.models.containers.Container
Crea e configura un container Docker per l'oggetto, con l'immagine specificata in `.container_image`.
.. method:: start(self) -> None
Tenta di creare e avviare un container Docker per l'oggetto, bloccando fino a quando esso non sarà avviato con `~.docker.sleep_until_container_has_started`.
.. method:: stop(self) -> None
Arresta il container Docker dell'oggetto.
Viewset dei notebook
^^^^^^^^^^^^^^^^^^^^
.. module:: sophon.notebooks.views
Come per il modulo `sophon.projects`, vengono creati due viewset per interagire con i progetti di ricerca, basati entrambi su un viewset astratto che ne definisce le proprietà comuni.
.. class:: NotebooksViewSet(SophonGroupViewSet, metaclass=abc.ABCMeta)
Classe **astratta** che effettua l'override di `~sophon.core.views.SophonGroupView.get_group_from_serializer` e definisce cinque azioni personalizzate per l'interazione con il notebook.
.. method:: sync(self, request: Request, **kwargs) -> Response
Azione personalizzata che sincronizza lo stato dell'oggetto dell'API con quello del daemon Docker.
.. method:: start(self, request: Request, **kwargs) -> Response
Azione personalizzata che avvia il notebook con `.models.Notebook.start`.
.. method:: stop(self, request: Request, **kwargs) -> Response
Azione personalizzata che arresta il notebook con `.models.Notebook.stop`.
.. method:: lock(self, request: Request, **kwargs) -> Response
Azione personalizzata che blocca il notebook impostando il campo `.models.Notebook.locked_by` all'utente che ha effettuato la richiesta.
.. method:: unlock(self, request: Request, **kwargs) -> Response
Azione personalizzata che sblocca il notebook impostando il campo `.models.Notebook.locked_by` a `None`.
.. class:: NotebooksBySlugViewSet(NotebooksViewSet)
Viewset in lettura e scrittura che permette di interagire con tutti i notebook a cui l'utente loggato ha accesso.
Accessibile all'URL :samp:`/api/notebooks/by-slug/{NOTEBOOK_SLUG}/`.
.. class:: NotebooksByProjectViewSet(NotebooksViewSet)
Viewset in lettura e scrittura che permette di interagire con i notebook a cui l'utente loggato ha accesso, filtrati per il progetto di appartenenza.
Accessibile all'URL :samp:`/api/notebooks/by-project/{PROJECT_SLUG}/{NOTEBOOK_SLUG/`.

View file

@ -0,0 +1,6 @@
Continuous Integration
----------------------
Il codice sorgente del modulo viene automaticamente controllato attraverso GitHub Actions da **CodeQL** e **Dependabot** ad ogni modifica, segnalando gli eventuali errori o dipendenze non aggiornate nel pannello *Security* del repository.
.. image:: ci_example.png

View file

@ -0,0 +1,12 @@
Continuous Deployment
---------------------
L'immagine del modulo viene automaticamente ricompilata da GitHub Actions e pubblicata su GitHub Containers ogni volta che un file all'interno della cartella del modulo viene modificato.
Questo workflow è definito all'interno del file ``.github/workflows/build-docker-backend.yml``.
.. image:: cd_example.png
.. seealso::
`La pagina del container <https://github.com/Steffo99/sophon/pkgs/container/sophon-backend>`_ su GitHub Containers.

BIN
report/source/3_dev/2_structure/1_backend/cd_example.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
report/source/3_dev/2_structure/1_backend/ci_example.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,28 @@
Modulo backend
==============
.. default-domain:: py
.. default-role:: obj
.. py:currentmodule:: sophon
Il *modulo backend* consiste in un server web che espone un'API e un sito web per l'amministrazione.
È collocato all'interno del repository in ``/backend``.
È formato dal package Python `sophon`, che contiene al suo interno un progetto Django, che a sua volta contiene le tre app Django `sophon.core`, `sophon.projects` e `sophon.notebooks`.
.. note::
A causa della dipendenza di Django da variabili globali, è stato impossibile utilizzare lo strumento di documentazione automatica `sphinx.ext.autodoc`.
Pertanto, si è deciso di documentare soltanto le classi e metodi più rilevanti ai fini di questa documentazione.
.. toctree::
:maxdepth: 1
1_techstack
2_sophon
3_core
4_projects
5_notebooks
6_ci
7_cd

Binary file not shown.

View file

@ -0,0 +1,17 @@
Librerie e tecnologie utilizzate
--------------------------------
.. note::
Sono elencate solo le principali librerie utilizzate; dipendenze e librerie minori non sono specificate, ma sono visibili all'interno del file ``yarn.lock``.
- I linguaggi di programmazione `JavaScript <https://developer.mozilla.org/en-US/docs/Web/JavaScript/About_JavaScript>`_ e `TypeScript <https://www.typescriptlang.org/>`_
- Il gestore di dipendenze `Yarn <https://yarnpkg.com/>`_
- La libreria grafica `Bluelib <https://github.com/Steffo99/bluelib>`_ (sviluppata come progetto personale nell'estate 2021)
- Il framework per interfacce grafiche `React <https://reactjs.org>`_
- Il router `Reach Router <https://reach.tech/router/>`_
- L'integrazione con React di Bluelib `bluelib-react <https://github.com/Steffo99/bluelib-react>`_ (sviluppata durante il tirocinio)
- Il componente React `react-markdown <https://github.com/remarkjs/react-markdown>`_
- Il framework per testing `Jest <https://jestjs.io/>`_
- Un fork personalizzato del client XHR `axios <https://github.com/axios/axios>`_
- Il webserver statico `serve <https://www.npmjs.com/package/serve>`_

View file

@ -0,0 +1,23 @@
Struttura delle directory
-------------------------
.. default-domain:: js
Le directory di :mod:`@steffo45/sophon-frontend` sono strutturate nella seguente maniera:
src/components
Contiene i componenti React sia con le classi sia funzionali.
src/contexts
Contiene i contesti React creati con :func:`React.createContext`.
src/hooks
Contiene gli hook React personalizzati utilizzati nei componenti funzionali.
src/types
Contiene estensioni ai tipi base TypeScript, come ad esempio i tipi restituiti dalla web API del :ref:`modulo backend`.
src/utils
Contiene varie funzioni di utility.
public
Contiene i file statici da servire assieme all'app.

Some files were not shown because too many files have changed in this diff Show more