mirror of
https://github.com/Steffo99/sophon.git
synced 2024-12-22 06:44:21 +00:00
🎓 Create thesis structure
This commit is contained in:
parent
9a6d9619b3
commit
7b3195cc3f
119 changed files with 59 additions and 2936 deletions
|
@ -1,22 +0,0 @@
|
|||
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
docs/source/1_user/2_concepts/1_instances/choose.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/1_instances/choose.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/1_instances/diagram.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/1_instances/diagram.png
(Stored with Git LFS)
Binary file not shown.
|
@ -1,26 +0,0 @@
|
|||
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
docs/source/1_user/2_concepts/1_instances/urls.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/1_instances/urls.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/2_users/creation.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/2_users/creation.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/2_users/diagram.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/2_users/diagram.png
(Stored with Git LFS)
Binary file not shown.
|
@ -1,58 +0,0 @@
|
|||
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
docs/source/1_user/2_concepts/2_users/login.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/2_users/login.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/3_researchgroups/choose.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/3_researchgroups/choose.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/3_researchgroups/creation.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/3_researchgroups/creation.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/3_researchgroups/diagram.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/3_researchgroups/diagram.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/3_researchgroups/icons.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/3_researchgroups/icons.png
(Stored with Git LFS)
Binary file not shown.
|
@ -1,69 +0,0 @@
|
|||
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
|
BIN
docs/source/1_user/2_concepts/3_researchgroups/join_manual.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/3_researchgroups/join_manual.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/3_researchgroups/join_open.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/3_researchgroups/join_open.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/3_researchgroups/list.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/3_researchgroups/list.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/4_researchprojects/creation.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/4_researchprojects/creation.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/4_researchprojects/diagram.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/4_researchprojects/diagram.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/4_researchprojects/icons.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/4_researchprojects/icons.png
(Stored with Git LFS)
Binary file not shown.
|
@ -1,68 +0,0 @@
|
|||
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
docs/source/1_user/2_concepts/4_researchprojects/list.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/4_researchprojects/list.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/5_notebooks/action_lock.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/5_notebooks/action_lock.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/5_notebooks/action_start.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/5_notebooks/action_start.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/5_notebooks/action_stop.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/5_notebooks/action_stop.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/5_notebooks/collaboration.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/5_notebooks/collaboration.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/5_notebooks/connection.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/5_notebooks/connection.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/5_notebooks/creation.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/5_notebooks/creation.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/5_notebooks/detail.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/5_notebooks/detail.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/5_notebooks/diagram.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/5_notebooks/diagram.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/5_notebooks/diagram_network.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/5_notebooks/diagram_network.png
(Stored with Git LFS)
Binary file not shown.
|
@ -1,155 +0,0 @@
|
|||
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
|
BIN
docs/source/1_user/2_concepts/5_notebooks/inside_the_lab.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/5_notebooks/inside_the_lab.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/5_notebooks/list.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/5_notebooks/list.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/5_notebooks/locked.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/5_notebooks/locked.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/5_notebooks/status_running.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/5_notebooks/status_running.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/5_notebooks/status_stopped.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/5_notebooks/status_stopped.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/2_concepts/diagram_full.png
(Stored with Git LFS)
BIN
docs/source/1_user/2_concepts/diagram_full.png
(Stored with Git LFS)
Binary file not shown.
|
@ -1,15 +0,0 @@
|
|||
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
docs/source/1_user/3_extras/confirm.png
(Stored with Git LFS)
BIN
docs/source/1_user/3_extras/confirm.png
(Stored with Git LFS)
Binary file not shown.
|
@ -1,72 +0,0 @@
|
|||
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
docs/source/1_user/3_extras/members_list.png
(Stored with Git LFS)
BIN
docs/source/1_user/3_extras/members_list.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/admin_login.png
(Stored with Git LFS)
BIN
docs/source/1_user/admin_login.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/classic_notebook.png
(Stored with Git LFS)
BIN
docs/source/1_user/classic_notebook.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/1_user/screenshots/admin_page.png
(Stored with Git LFS)
BIN
docs/source/1_user/screenshots/admin_page.png
(Stored with Git LFS)
Binary file not shown.
|
@ -1,21 +0,0 @@
|
|||
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/
|
|
@ -1,30 +0,0 @@
|
|||
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]
|
|
@ -1,17 +0,0 @@
|
|||
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/``).
|
|
@ -1,222 +0,0 @@
|
|||
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.
|
|
@ -1,48 +0,0 @@
|
|||
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/
|
|
@ -1,22 +0,0 @@
|
|||
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/
|
|
@ -1,62 +0,0 @@
|
|||
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
|
|
@ -1,4 +0,0 @@
|
|||
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`.
|
|
@ -1,18 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
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
|
|
@ -1,112 +0,0 @@
|
|||
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
docs/source/2_admin/2_administration/admin_home.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/admin_home.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/admin_login.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/admin_login.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/admin_where.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/admin_where.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/custom_description.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/custom_description.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/custom_title.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/custom_title.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/customization.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/customization.png
(Stored with Git LFS)
Binary file not shown.
|
@ -1,9 +0,0 @@
|
|||
Amministrazione
|
||||
***************
|
||||
|
||||
Questo capitolo fornisce informazioni su come amministrare un':ref:`istanza` Sophon.
|
||||
|
||||
.. toctree::
|
||||
|
||||
1_admin_panel
|
||||
2_entities
|
BIN
docs/source/2_admin/2_administration/notebook_detail.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/notebook_detail.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/notebook_list.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/notebook_list.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/researchgroup_detail.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/researchgroup_detail.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/researchgroup_list.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/researchgroup_list.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/researchproject_detail.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/researchproject_detail.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/researchproject_list.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/researchproject_list.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/theme_amber.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/theme_amber.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/theme_hacker.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/theme_hacker.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/theme_paper.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/theme_paper.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/theme_royalblue.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/theme_royalblue.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/theme_sophon.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/theme_sophon.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/token_detail.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/token_detail.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/token_list.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/token_list.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/topright.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/topright.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/user_detail.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/user_detail.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/2_admin/2_administration/user_list.png
(Stored with Git LFS)
BIN
docs/source/2_admin/2_administration/user_list.png
(Stored with Git LFS)
Binary file not shown.
|
@ -1,21 +0,0 @@
|
|||
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/
|
|
@ -1,27 +0,0 @@
|
|||
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
|
|
@ -1,40 +0,0 @@
|
|||
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.
|
|
@ -1,16 +0,0 @@
|
|||
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>`_
|
|
@ -1,89 +0,0 @@
|
|||
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.
|
|
@ -1,333 +0,0 @@
|
|||
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.
|
||||
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
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.
|
|
@ -1,241 +0,0 @@
|
|||
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/`.
|
|
@ -1,6 +0,0 @@
|
|||
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
|
|
@ -1,12 +0,0 @@
|
|||
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
docs/source/3_dev/2_structure/1_backend/cd_example.png
(Stored with Git LFS)
BIN
docs/source/3_dev/2_structure/1_backend/cd_example.png
(Stored with Git LFS)
Binary file not shown.
BIN
docs/source/3_dev/2_structure/1_backend/ci_example.png
(Stored with Git LFS)
BIN
docs/source/3_dev/2_structure/1_backend/ci_example.png
(Stored with Git LFS)
Binary file not shown.
|
@ -1,28 +0,0 @@
|
|||
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
|
BIN
docs/source/3_dev/2_structure/1_backend/notebooks_diagram.png
(Stored with Git LFS)
BIN
docs/source/3_dev/2_structure/1_backend/notebooks_diagram.png
(Stored with Git LFS)
Binary file not shown.
|
@ -1,17 +0,0 @@
|
|||
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>`_
|
|
@ -1,23 +0,0 @@
|
|||
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.
|
|
@ -1,113 +0,0 @@
|
|||
Comunicazione con il server
|
||||
---------------------------
|
||||
.. default-domain:: js
|
||||
|
||||
|
||||
Axios
|
||||
^^^^^
|
||||
|
||||
Per effettuare richieste all'API web, si è deciso di utilizzare la libreria :mod:`axios`, in quanto permette di creare dei "client" personalizzabili con varie proprietà.
|
||||
|
||||
In particolare, si è scelto di forkarla, integrando anticipatamente una proposta di funzionalità che permette alle richieste di essere interrotte attraverso degli :class:`AbortController`.
|
||||
|
||||
|
||||
Client personalizzati
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Per permettere all'utente di selezionare l'istanza da utilizzare e di comunicare con l'API con le proprie credenziali, si è scelto di creare client personalizzati partendo da due contesti.
|
||||
|
||||
All'interno di un contesto in cui è stata selezionata un'istanza (:data:`InstanceContext`), viene creato un client dal seguente hook:
|
||||
|
||||
.. function:: useInstanceAxios(config = {})
|
||||
|
||||
Questo hook specifica il ``baseURL`` del client Axios, impostandolo all'URL dell'istanza selezionata.
|
||||
|
||||
All'interno di un contesto in cui è stato effettuato l'accesso come utente (:data:`AuthorizationContext`), viene creato invece un client dal seguente hook:
|
||||
|
||||
.. function:: useAuthorizedAxios(config = {})
|
||||
|
||||
Questo hook specifica il valore dell'header ``Authorization`` da inviare in tutte le richieste effettuate a :samp:`Bearer {TOKEN}`, utilizzando il token ottenuto al momento dell'accesso.
|
||||
|
||||
|
||||
Utilizzo di viewset
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Viene implementato un hook che si integra con i viewset di Django, fornendo un API semplificato per effettuare azioni su di essi.
|
||||
|
||||
.. function:: useViewSet(baseRoute)
|
||||
|
||||
Questo hook implementa tutte le azioni :py:mod:`rest_framework` di un viewset in lettura e scrittura.
|
||||
|
||||
Richiede di essere chiamato all'interno di un :data:`AuthorizationContext`.
|
||||
|
||||
.. function:: async list(config = {})
|
||||
.. function:: async retrieve(pk, config = {})
|
||||
.. function:: async create(config)
|
||||
.. function:: async update(pk, config)
|
||||
.. function:: async destroy(pk, config)
|
||||
|
||||
Viene inoltre fornito supporto per le azioni personalizzate.
|
||||
|
||||
.. function:: async command(config)
|
||||
|
||||
Permette azioni personalizzate su tutto il viewset.
|
||||
|
||||
.. function:: async action(config)
|
||||
|
||||
Permette azioni personalizzate su uno specifico oggetto del viewset.
|
||||
|
||||
|
||||
Emulazione di viewset
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Viene creato un hook che tiene traccia degli oggetti restituiti da un determinato viewset, ed emula i risultati delle azioni effettuate, minimizzando i rerender e ottenendo una ottima user experience.
|
||||
|
||||
.. function:: useManagedViewSet(baseRoute, pkKey, refreshOnMount)
|
||||
|
||||
.. attribute:: viewset
|
||||
|
||||
Il viewset restituito da :func:`useViewSet`, utilizzato come interfaccia di basso livello per effettuare azioni.
|
||||
|
||||
.. attribute:: state
|
||||
|
||||
Lo stato del viewset, che tiene traccia degli oggetti e delle azioni in corso su di essi.
|
||||
|
||||
Gli oggetti all'interno di esso sono istanze di :class:`ManagedResource`, create usando wrapper di :func:`.update`, :func:`.destroy` e :func:`.action`, che permettono di modificare direttamente l'oggetto senza preoccuparsi dell'indice a cui si trova nell'array.
|
||||
|
||||
.. attribute:: dispatch
|
||||
|
||||
Riduttore che permette di alterare lo :attr:`.state`.
|
||||
|
||||
.. function:: async refresh()
|
||||
|
||||
Ricarica gli oggetti del viewset.
|
||||
|
||||
Viene chiamata automaticamente al primo render se ``refreshOnMount`` è :data:`True`.
|
||||
|
||||
.. function:: async create(data)
|
||||
|
||||
Crea un nuovo oggetto nel viewset con i dati specificati come argomento, e lo aggiunge allo stato se la richiesta va a buon fine.
|
||||
|
||||
.. function:: async command(method, cmd, data)
|
||||
|
||||
Esegue l'azione personalizzata ``cmd`` su tutto il viewset, utilizzando il metodo ``method`` e con i dati specificati in ``data``.
|
||||
|
||||
Se la richiesta va a buon fine, il valore restituito dal backend sostituisce nello stato le risorse dell'intero viewset.
|
||||
|
||||
.. function:: async update(index, data)
|
||||
|
||||
Modifica l'oggetto alla posizione ``index`` dell'array :attr:`.state` con i dati specificati in ``data``.
|
||||
|
||||
Se la richiesta va a buon fine, la modifica viene anche applicata all'interno di :attr:`.state`
|
||||
|
||||
.. function:: async destroy(index)
|
||||
|
||||
Elimina l'oggetto alla posizione ``index`` dell'array :attr:`.state`.
|
||||
|
||||
Se la richiesta va a buon fine, l'oggetto viene eliminato anche da :attr:`.state`.
|
||||
|
||||
.. function:: async action(index, method, act, data)
|
||||
|
||||
Esegue l'azione personalizzata ``act`` sull'oggetto alla posizione ``index`` dell'array :attr:`.state`, utilizzando il metodo ``method`` e con i dati specificati in ``data``.
|
||||
|
||||
Se la richiesta va a buon fine, il valore restituito dal backend sostituisce l'oggetto utilizzato in :attr:`.state`.
|
|
@ -1,162 +0,0 @@
|
|||
Contesti innestati
|
||||
------------------
|
||||
.. default-domain:: js
|
||||
|
||||
Per minimizzare i rerender, l'applicazione è organizzata a "contesti innestati".
|
||||
|
||||
|
||||
I contesti
|
||||
^^^^^^^^^^
|
||||
|
||||
Viene definito un contesto per ogni tipo di risorsa selezionabile nell'interfaccia.
|
||||
|
||||
Essi sono, in ordine dal più esterno al più interno:
|
||||
|
||||
#. :data:`InstanceContext` (:ref:`Istanza`)
|
||||
#. :data:`AuthorizationContext` (:ref:`Utente`)
|
||||
#. :data:`GroupContext` (:ref:`Gruppo di ricerca`)
|
||||
#. :data:`ProjectContext` (:ref:`Progetto di ricerca`)
|
||||
#. :data:`NotebookContext` (:ref:`Notebook`)
|
||||
|
||||
|
||||
Contenuto dei contesti
|
||||
""""""""""""""""""""""
|
||||
|
||||
Questi contesti possono avere tre tipi di valori: :data:`undefined` se ci si trova al di fuori del contesto, :data:`null` se non è stato selezionato alcun oggetto oppure **l'oggetto selezionato** se esso esiste.
|
||||
|
||||
|
||||
URL contestuale
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Si è definita la seguente struttura per gli URL del frontend di Sophon, in modo che essi identificassero universalmente una risorsa e che essi fossero human-readable.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
/i/{ISTANZA}
|
||||
/l/logged-in
|
||||
/g/{GROUP_SLUG}
|
||||
/p/{PROJECT_SLUG}
|
||||
/n/{NOTEBOOK_SLUG}/
|
||||
|
||||
Ad esempio, l'URL per il notebook ``my-first-notebook`` dell'istanza demo di Sophon sarebbe:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
/i/https:api.prod.sophon.steffo.eu:
|
||||
/l/logged-in
|
||||
/g/my-first-group
|
||||
/p/my-first-project
|
||||
/n/my-first-notebook/
|
||||
|
||||
|
||||
Parsing degli URL contestuali
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Viene definita una funzione in grado di comprendere gli URL contestuali:
|
||||
|
||||
.. function:: parsePath(path)
|
||||
|
||||
:param path: Il "path" da leggere.
|
||||
:returns:
|
||||
Un oggetto con le seguenti chiavi, dette "segmenti di percorso", le quali possono essere :data:`undefined` per indicare che non è stato selezionato un oggetto di quel tipo:
|
||||
|
||||
- ``instance``: l'URL dell'istanza da utilizzare, con caratteri speciali sostituiti da ``:``
|
||||
- ``loggedIn``: :class:`Boolean`, se :data:`True` l'utente ha effettuato il login (come :ref:`Ospite` o :ref:`Utente`)
|
||||
- ``researchGroup``: lo slug del :ref:`gruppo di ricerca` selezionato
|
||||
- ``researchProject``: lo slug del :ref:`progetto di ricerca` selezionato
|
||||
- ``notebook``: lo slug del :ref:`notebook` selezionato
|
||||
|
||||
Ad esempio, l'URL precedente restituirebbe il seguente oggetto se processato:
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
{
|
||||
"instance": "https:api.prod.sophon.steffo.eu:",
|
||||
"loggedIn": True,
|
||||
"researchGroup": "my-first-group",
|
||||
"researchProject": "my-first-project",
|
||||
"notebook": "my-first-notebook"
|
||||
}
|
||||
|
||||
|
||||
Routing basato sui contesti
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
I valori dei contesti vengono utilizzati per selezionare i componenti da mostrare all'utente nell'interfaccia grafica attraverso i seguenti componenti:
|
||||
|
||||
.. function:: ResourceRouter({selection, unselectedRoute, selectedRoute})
|
||||
|
||||
Componente che sceglie se renderizzare ``unselectedRoute`` o ``selectedRoute`` in base alla *nullità* o *non-nullità* di ``selection``.
|
||||
|
||||
.. function:: ViewSetRouter({viewSet, unselectedRoute, selectedRoute, pathSegment, pkKey})
|
||||
|
||||
Componente basato su :func:`ResourceRouter` che seleziona automaticamente l'elemento del viewset avente il valore del segmento di percorso ``pathSegment`` alla chiave ``pkKey``.
|
||||
|
||||
|
||||
Esempio di utilizzo di ViewSetRouter
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
.. function:: GroupRouter({...props})
|
||||
|
||||
Implementato come:
|
||||
|
||||
.. code-block:: tsx
|
||||
|
||||
<ViewSetRouter
|
||||
{...props}
|
||||
viewSet={useManagedViewSet<SophonResearchGroup>("/api/core/groups/", "slug")}
|
||||
pathSegment={"researchGroup"}
|
||||
pkKey={"slug"}
|
||||
/>
|
||||
|
||||
|
||||
Albero completo dei contesti
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
L'insieme di tutti i contesti è definito come componente :func:`App` nel modulo "principale" ``App.tsx``.
|
||||
|
||||
Se ne riassume la struttura in pseudocodice:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<InstanceContext>
|
||||
<InstanceRouter>
|
||||
unselected:
|
||||
<InstanceSelect>
|
||||
selected:
|
||||
<AuthorizationContext>
|
||||
<AuthorizationRouter>
|
||||
unselected:
|
||||
<UserLogin>
|
||||
selected:
|
||||
<GroupContext>
|
||||
<GroupRouter>
|
||||
unselected:
|
||||
<GroupSelect>
|
||||
selected:
|
||||
<ProjectContext>
|
||||
<ProjectRouter>
|
||||
unselected:
|
||||
<ProjectSelect>
|
||||
selected:
|
||||
<NotebookContext>
|
||||
<NotebookRouter>
|
||||
unselected:
|
||||
<NotebookSelect>
|
||||
selected:
|
||||
<NotebookDetails>
|
||||
|
||||
|
||||
Altri contesti
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Tema
|
||||
""""
|
||||
|
||||
Il tema dell'istanza è implementato come uno speciale contesto globale :data:`ThemeContext` che riceve i dettagli dell'istanza a cui si è collegati dall':data:`InstanceContext`.
|
||||
|
||||
|
||||
Cache
|
||||
"""""
|
||||
|
||||
Viene salvato l'elenco di tutti i membri dell':ref:`istanza` in uno speciale contesto :data:`CacheContext` in modo da poter risolvere gli id degli utenti al loro username senza dover effettuare ulteriori richieste.
|
|
@ -1,6 +0,0 @@
|
|||
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
|
|
@ -1,12 +0,0 @@
|
|||
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-frontend.yml``.
|
||||
|
||||
.. image:: cd_example.png
|
||||
|
||||
.. seealso::
|
||||
|
||||
`La pagina del container <https://github.com/Steffo99/sophon/pkgs/container/sophon-frontend>`_ su GitHub Containers.
|
BIN
docs/source/3_dev/2_structure/2_frontend/cd_example.png
(Stored with Git LFS)
BIN
docs/source/3_dev/2_structure/2_frontend/cd_example.png
(Stored with Git LFS)
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue