From 66c94d4c870a4258867daabc1e501c43b1778350 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 14 Nov 2021 04:28:50 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A8=20Move=20around=20some=20files?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- backend/Backend.iml | 14 +- {docs => report}/.gitattributes | 0 {docs => report}/Makefile | 0 {docs => report}/make.bat | 0 report/source/1_user/1_about/index.rst | 22 ++ .../1_user/2_concepts/1_instances/choose.png | 3 + .../1_user/2_concepts/1_instances/diagram.png | 3 + .../1_user/2_concepts/1_instances/index.rst | 26 ++ .../1_user/2_concepts/1_instances/urls.png | 3 + .../1_user/2_concepts/2_users/creation.png | 3 + .../1_user/2_concepts/2_users/diagram.png | 3 + .../1_user/2_concepts/2_users/index.rst | 58 +++ .../1_user/2_concepts/2_users/login.png | 3 + .../2_concepts/3_researchgroups/choose.png | 3 + .../2_concepts/3_researchgroups/creation.png | 3 + .../2_concepts/3_researchgroups/diagram.png | 3 + .../2_concepts/3_researchgroups/icons.png | 3 + .../2_concepts/3_researchgroups/index.rst | 69 ++++ .../3_researchgroups/join_manual.png | 3 + .../2_concepts/3_researchgroups/join_open.png | 3 + .../2_concepts/3_researchgroups/list.png | 3 + .../4_researchprojects/creation.png | 3 + .../2_concepts/4_researchprojects/diagram.png | 3 + .../2_concepts/4_researchprojects/icons.png | 3 + .../2_concepts/4_researchprojects/index.rst | 68 ++++ .../2_concepts/4_researchprojects/list.png | 3 + .../2_concepts/5_notebooks/action_lock.png | 3 + .../2_concepts/5_notebooks/action_start.png | 3 + .../2_concepts/5_notebooks/action_stop.png | 3 + .../2_concepts/5_notebooks/collaboration.png | 3 + .../2_concepts/5_notebooks/connection.png | 3 + .../2_concepts/5_notebooks/creation.png | 3 + .../1_user/2_concepts/5_notebooks/detail.png | 3 + .../1_user/2_concepts/5_notebooks/diagram.png | 3 + .../5_notebooks/diagram_network.png | 3 + .../1_user/2_concepts/5_notebooks/index.rst | 155 ++++++++ .../2_concepts/5_notebooks/inside_the_lab.png | 3 + .../1_user/2_concepts/5_notebooks/list.png | 0 .../1_user/2_concepts/5_notebooks/locked.png | 3 + .../2_concepts/5_notebooks/status_running.png | 3 + .../2_concepts/5_notebooks/status_stopped.png | 3 + .../source/1_user/2_concepts/diagram_full.png | 3 + report/source/1_user/2_concepts/index.rst | 15 + report/source/1_user/3_extras/confirm.png | 3 + report/source/1_user/3_extras/index.rst | 72 ++++ .../source/1_user/3_extras/members_list.png | 3 + report/source/1_user/admin_login.png | 3 + report/source/1_user/classic_notebook.png | 3 + .../source/1_user/screenshots/admin_page.png | 3 + .../2_admin/1_installation/1_requirements.rst | 21 ++ .../1_installation/2_preparing_compose.rst | 30 ++ .../1_installation/3_configuring_dns.rst | 17 + .../1_installation/4_configuring_compose.rst | 222 ++++++++++++ .../1_installation/5_pulling_images.rst | 48 +++ .../1_installation/6_starting_sophon.rst | 22 ++ .../1_installation/7_host_reverse_proxy.rst | 62 ++++ .../2_admin/1_installation/8_final_check.rst | 4 + .../source/2_admin/1_installation/index.rst | 18 + .../2_administration/1_admin_panel.rst | 32 ++ .../2_admin/2_administration/2_entities.rst | 112 ++++++ .../2_admin/2_administration/admin_home.png | 3 + .../2_admin/2_administration/admin_login.png | 3 + .../2_admin/2_administration/admin_where.png | 3 + .../2_administration/custom_description.png | 3 + .../2_admin/2_administration/custom_title.png | 3 + .../2_administration/customization.png | 3 + .../source/2_admin/2_administration/index.rst | 9 + .../2_administration/notebook_detail.png | 3 + .../2_administration/notebook_list.png | 3 + .../2_administration/researchgroup_detail.png | 3 + .../2_administration/researchgroup_list.png | 3 + .../researchproject_detail.png | 3 + .../2_administration/researchproject_list.png | 3 + .../2_admin/2_administration/theme_amber.png | 3 + .../2_admin/2_administration/theme_hacker.png | 3 + .../2_admin/2_administration/theme_paper.png | 3 + .../2_administration/theme_royalblue.png | 3 + .../2_admin/2_administration/theme_sophon.png | 3 + .../2_admin/2_administration/token_detail.png | 3 + .../2_admin/2_administration/token_list.png | 3 + .../2_admin/2_administration/topright.png | 3 + .../2_admin/2_administration/user_detail.png | 3 + .../2_admin/2_administration/user_list.png | 3 + report/source/2_admin/3_update/index.rst | 21 ++ .../source/2_admin/4_uninstallation/index.rst | 27 ++ report/source/3_dev/1_tools/index.rst | 40 +++ .../2_structure/1_backend/1_techstack.rst | 16 + .../3_dev/2_structure/1_backend/2_sophon.rst | 89 +++++ .../3_dev/2_structure/1_backend/3_core.rst | 333 ++++++++++++++++++ .../2_structure/1_backend/4_projects.rst | 62 ++++ .../2_structure/1_backend/5_notebooks.rst | 241 +++++++++++++ .../3_dev/2_structure/1_backend/6_ci.rst | 6 + .../3_dev/2_structure/1_backend/7_cd.rst | 12 + .../2_structure/1_backend/cd_example.png | 3 + .../2_structure/1_backend/ci_example.png | 3 + .../3_dev/2_structure/1_backend/index.rst | 28 ++ .../1_backend/notebooks_diagram.png | 3 + .../2_structure/2_frontend/1_techstack.rst | 17 + .../3_dev/2_structure/2_frontend/2_tree.rst | 23 ++ .../2_structure/2_frontend/3_resources.rst | 113 ++++++ .../2_structure/2_frontend/4_contexts.rst | 162 +++++++++ .../3_dev/2_structure/2_frontend/5_ci.rst | 6 + .../3_dev/2_structure/2_frontend/6_cd.rst | 12 + .../2_structure/2_frontend/cd_example.png | 3 + .../2_structure/2_frontend/ci_example.png | 3 + .../3_dev/2_structure/2_frontend/index.rst | 22 ++ .../3_dev/2_structure/3_proxy/index.rst | 111 ++++++ .../3_dev/2_structure/4_jupyter/index.rst | 87 +++++ report/source/3_dev/2_structure/index.rst | 13 + report/source/3_dev/3_differences/index.rst | 27 ++ report/source/3_dev/4_tests/index.rst | 130 +++++++ report/source/3_dev/5_license/index.rst | 12 + .../source/_static/group_delete_confirm.mp4 | 0 report/source/conf.py | 148 ++++++++ report/source/index.rst | 46 +++ thesis/.gitattributes | 1 + thesis/Makefile | 25 ++ thesis/make.bat | 35 ++ .../source/_static/group_delete_confirm.mp4 | 3 + {docs => thesis}/source/conf.py | 0 .../source/docs/1_sinossi/index.rst | 0 thesis/source/docs/1_sinossi/screenshot.png | 3 + .../source/docs/2_introduzione/index.rst | 0 .../source/docs/3_presentazione/index.rst | 0 .../source/docs/4_requisiti/index.rst | 0 .../source/docs/5_progetto/index.rst | 0 .../source/docs/6_implementazione/index.rst | 0 .../source/docs/6_implementazione/tech.rst | 0 .../source/docs/7_applicazione/index.rst | 0 .../source/docs/8_conclusione/index.rst | 0 .../source/docs/9_appendice/index.rst | 0 {docs => thesis}/source/index.rst | 0 {docs => thesis}/source/refs.bib | 0 134 files changed, 3151 insertions(+), 7 deletions(-) rename {docs => report}/.gitattributes (100%) rename {docs => report}/Makefile (100%) rename {docs => report}/make.bat (100%) create mode 100644 report/source/1_user/1_about/index.rst create mode 100644 report/source/1_user/2_concepts/1_instances/choose.png create mode 100644 report/source/1_user/2_concepts/1_instances/diagram.png create mode 100644 report/source/1_user/2_concepts/1_instances/index.rst create mode 100644 report/source/1_user/2_concepts/1_instances/urls.png create mode 100644 report/source/1_user/2_concepts/2_users/creation.png create mode 100644 report/source/1_user/2_concepts/2_users/diagram.png create mode 100644 report/source/1_user/2_concepts/2_users/index.rst create mode 100644 report/source/1_user/2_concepts/2_users/login.png create mode 100644 report/source/1_user/2_concepts/3_researchgroups/choose.png create mode 100644 report/source/1_user/2_concepts/3_researchgroups/creation.png create mode 100644 report/source/1_user/2_concepts/3_researchgroups/diagram.png create mode 100644 report/source/1_user/2_concepts/3_researchgroups/icons.png create mode 100644 report/source/1_user/2_concepts/3_researchgroups/index.rst create mode 100644 report/source/1_user/2_concepts/3_researchgroups/join_manual.png create mode 100644 report/source/1_user/2_concepts/3_researchgroups/join_open.png create mode 100644 report/source/1_user/2_concepts/3_researchgroups/list.png create mode 100644 report/source/1_user/2_concepts/4_researchprojects/creation.png create mode 100644 report/source/1_user/2_concepts/4_researchprojects/diagram.png create mode 100644 report/source/1_user/2_concepts/4_researchprojects/icons.png create mode 100644 report/source/1_user/2_concepts/4_researchprojects/index.rst create mode 100644 report/source/1_user/2_concepts/4_researchprojects/list.png create mode 100644 report/source/1_user/2_concepts/5_notebooks/action_lock.png create mode 100644 report/source/1_user/2_concepts/5_notebooks/action_start.png create mode 100644 report/source/1_user/2_concepts/5_notebooks/action_stop.png create mode 100644 report/source/1_user/2_concepts/5_notebooks/collaboration.png create mode 100644 report/source/1_user/2_concepts/5_notebooks/connection.png create mode 100644 report/source/1_user/2_concepts/5_notebooks/creation.png create mode 100644 report/source/1_user/2_concepts/5_notebooks/detail.png create mode 100644 report/source/1_user/2_concepts/5_notebooks/diagram.png create mode 100644 report/source/1_user/2_concepts/5_notebooks/diagram_network.png create mode 100644 report/source/1_user/2_concepts/5_notebooks/index.rst create mode 100644 report/source/1_user/2_concepts/5_notebooks/inside_the_lab.png rename docs/source/docs/1_sinossi/screenshot.png => report/source/1_user/2_concepts/5_notebooks/list.png (100%) create mode 100644 report/source/1_user/2_concepts/5_notebooks/locked.png create mode 100644 report/source/1_user/2_concepts/5_notebooks/status_running.png create mode 100644 report/source/1_user/2_concepts/5_notebooks/status_stopped.png create mode 100644 report/source/1_user/2_concepts/diagram_full.png create mode 100644 report/source/1_user/2_concepts/index.rst create mode 100644 report/source/1_user/3_extras/confirm.png create mode 100644 report/source/1_user/3_extras/index.rst create mode 100644 report/source/1_user/3_extras/members_list.png create mode 100644 report/source/1_user/admin_login.png create mode 100644 report/source/1_user/classic_notebook.png create mode 100644 report/source/1_user/screenshots/admin_page.png create mode 100644 report/source/2_admin/1_installation/1_requirements.rst create mode 100644 report/source/2_admin/1_installation/2_preparing_compose.rst create mode 100644 report/source/2_admin/1_installation/3_configuring_dns.rst create mode 100644 report/source/2_admin/1_installation/4_configuring_compose.rst create mode 100644 report/source/2_admin/1_installation/5_pulling_images.rst create mode 100644 report/source/2_admin/1_installation/6_starting_sophon.rst create mode 100644 report/source/2_admin/1_installation/7_host_reverse_proxy.rst create mode 100644 report/source/2_admin/1_installation/8_final_check.rst create mode 100644 report/source/2_admin/1_installation/index.rst create mode 100644 report/source/2_admin/2_administration/1_admin_panel.rst create mode 100644 report/source/2_admin/2_administration/2_entities.rst create mode 100644 report/source/2_admin/2_administration/admin_home.png create mode 100644 report/source/2_admin/2_administration/admin_login.png create mode 100644 report/source/2_admin/2_administration/admin_where.png create mode 100644 report/source/2_admin/2_administration/custom_description.png create mode 100644 report/source/2_admin/2_administration/custom_title.png create mode 100644 report/source/2_admin/2_administration/customization.png create mode 100644 report/source/2_admin/2_administration/index.rst create mode 100644 report/source/2_admin/2_administration/notebook_detail.png create mode 100644 report/source/2_admin/2_administration/notebook_list.png create mode 100644 report/source/2_admin/2_administration/researchgroup_detail.png create mode 100644 report/source/2_admin/2_administration/researchgroup_list.png create mode 100644 report/source/2_admin/2_administration/researchproject_detail.png create mode 100644 report/source/2_admin/2_administration/researchproject_list.png create mode 100644 report/source/2_admin/2_administration/theme_amber.png create mode 100644 report/source/2_admin/2_administration/theme_hacker.png create mode 100644 report/source/2_admin/2_administration/theme_paper.png create mode 100644 report/source/2_admin/2_administration/theme_royalblue.png create mode 100644 report/source/2_admin/2_administration/theme_sophon.png create mode 100644 report/source/2_admin/2_administration/token_detail.png create mode 100644 report/source/2_admin/2_administration/token_list.png create mode 100644 report/source/2_admin/2_administration/topright.png create mode 100644 report/source/2_admin/2_administration/user_detail.png create mode 100644 report/source/2_admin/2_administration/user_list.png create mode 100644 report/source/2_admin/3_update/index.rst create mode 100644 report/source/2_admin/4_uninstallation/index.rst create mode 100644 report/source/3_dev/1_tools/index.rst create mode 100644 report/source/3_dev/2_structure/1_backend/1_techstack.rst create mode 100644 report/source/3_dev/2_structure/1_backend/2_sophon.rst create mode 100644 report/source/3_dev/2_structure/1_backend/3_core.rst create mode 100644 report/source/3_dev/2_structure/1_backend/4_projects.rst create mode 100644 report/source/3_dev/2_structure/1_backend/5_notebooks.rst create mode 100644 report/source/3_dev/2_structure/1_backend/6_ci.rst create mode 100644 report/source/3_dev/2_structure/1_backend/7_cd.rst create mode 100644 report/source/3_dev/2_structure/1_backend/cd_example.png create mode 100644 report/source/3_dev/2_structure/1_backend/ci_example.png create mode 100644 report/source/3_dev/2_structure/1_backend/index.rst create mode 100644 report/source/3_dev/2_structure/1_backend/notebooks_diagram.png create mode 100644 report/source/3_dev/2_structure/2_frontend/1_techstack.rst create mode 100644 report/source/3_dev/2_structure/2_frontend/2_tree.rst create mode 100644 report/source/3_dev/2_structure/2_frontend/3_resources.rst create mode 100644 report/source/3_dev/2_structure/2_frontend/4_contexts.rst create mode 100644 report/source/3_dev/2_structure/2_frontend/5_ci.rst create mode 100644 report/source/3_dev/2_structure/2_frontend/6_cd.rst create mode 100644 report/source/3_dev/2_structure/2_frontend/cd_example.png create mode 100644 report/source/3_dev/2_structure/2_frontend/ci_example.png create mode 100644 report/source/3_dev/2_structure/2_frontend/index.rst create mode 100644 report/source/3_dev/2_structure/3_proxy/index.rst create mode 100644 report/source/3_dev/2_structure/4_jupyter/index.rst create mode 100644 report/source/3_dev/2_structure/index.rst create mode 100644 report/source/3_dev/3_differences/index.rst create mode 100644 report/source/3_dev/4_tests/index.rst create mode 100644 report/source/3_dev/5_license/index.rst rename {docs => report}/source/_static/group_delete_confirm.mp4 (100%) create mode 100644 report/source/conf.py create mode 100644 report/source/index.rst create mode 100644 thesis/.gitattributes create mode 100644 thesis/Makefile create mode 100644 thesis/make.bat create mode 100644 thesis/source/_static/group_delete_confirm.mp4 rename {docs => thesis}/source/conf.py (100%) rename {docs => thesis}/source/docs/1_sinossi/index.rst (100%) create mode 100644 thesis/source/docs/1_sinossi/screenshot.png rename {docs => thesis}/source/docs/2_introduzione/index.rst (100%) rename {docs => thesis}/source/docs/3_presentazione/index.rst (100%) rename {docs => thesis}/source/docs/4_requisiti/index.rst (100%) rename {docs => thesis}/source/docs/5_progetto/index.rst (100%) rename {docs => thesis}/source/docs/6_implementazione/index.rst (100%) rename {docs => thesis}/source/docs/6_implementazione/tech.rst (100%) rename {docs => thesis}/source/docs/7_applicazione/index.rst (100%) rename {docs => thesis}/source/docs/8_conclusione/index.rst (100%) rename {docs => thesis}/source/docs/9_appendice/index.rst (100%) rename {docs => thesis}/source/index.rst (100%) rename {docs => thesis}/source/refs.bib (100%) diff --git a/.gitignore b/.gitignore index f755eec..a51c4ed 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ proxy.dbm -docs/build +thesis/build diff --git a/backend/Backend.iml b/backend/Backend.iml index 2e650ae..da1c48e 100644 --- a/backend/Backend.iml +++ b/backend/Backend.iml @@ -17,11 +17,13 @@ - - - - - + + + + + + + @@ -31,7 +33,7 @@ diff --git a/docs/.gitattributes b/report/.gitattributes similarity index 100% rename from docs/.gitattributes rename to report/.gitattributes diff --git a/docs/Makefile b/report/Makefile similarity index 100% rename from docs/Makefile rename to report/Makefile diff --git a/docs/make.bat b/report/make.bat similarity index 100% rename from docs/make.bat rename to report/make.bat diff --git a/report/source/1_user/1_about/index.rst b/report/source/1_user/1_about/index.rst new file mode 100644 index 0000000..43db44c --- /dev/null +++ b/report/source/1_user/1_about/index.rst @@ -0,0 +1,22 @@ +Il progetto in breve +******************** + +*Sophon* è una applicazione web realizzata nel 2021 da Stefano Pigozzi per conto del `dipartimento di Informatica`_ dell'`Università di Modena e Reggio Emilia`_. + +Sophon permette ai suoi utenti di effettuare in sicurezza attività di ricerca collaborativa da remoto, sfruttando le macchine dell'istituzione di loro appartenenza per l'elaborazione dei dati. + +.. _dipartimento di Informatica: https://www.fim.unimore.it/ +.. _Università di Modena e Reggio Emilia: https://www.unimore.it/ + + +Screenshots +=========== + +.. image:: ../2_concepts/1_instances/choose.png +.. image:: ../2_concepts/2_users/login.png +.. image:: ../2_concepts/3_researchgroups/list.png +.. image:: ../2_concepts/4_researchprojects/list.png +.. image:: ../2_concepts/5_notebooks/list.png +.. image:: ../2_concepts/5_notebooks/detail.png +.. image:: ../2_concepts/5_notebooks/inside_the_lab.png +.. image:: ../../2_admin/2_administration/admin_home.png diff --git a/report/source/1_user/2_concepts/1_instances/choose.png b/report/source/1_user/2_concepts/1_instances/choose.png new file mode 100644 index 0000000..012ea57 --- /dev/null +++ b/report/source/1_user/2_concepts/1_instances/choose.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:885b53c2425841d8f619a2b4142d2512f0380799ee7eb04475fd1600e259ba3c +size 39049 diff --git a/report/source/1_user/2_concepts/1_instances/diagram.png b/report/source/1_user/2_concepts/1_instances/diagram.png new file mode 100644 index 0000000..f8f3dc1 --- /dev/null +++ b/report/source/1_user/2_concepts/1_instances/diagram.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b724c49caa314083dddd914727d6b2c718cb50a9104635b09c7055cec7deefa6 +size 22041 diff --git a/report/source/1_user/2_concepts/1_instances/index.rst b/report/source/1_user/2_concepts/1_instances/index.rst new file mode 100644 index 0000000..a6aa7fe --- /dev/null +++ b/report/source/1_user/2_concepts/1_instances/index.rst @@ -0,0 +1,26 @@ +Istanza +======= + +Un'*istanza* rappresenta un'**installazione di Sophon** effettuata su un server di un'istituzione di ricerca, come ad esempio un'Università. + +Ogni istanza è **fisicamente e logicamente separata** dalle altre; istanze diverse **non condividono alcun dato** tra loro. + +.. image:: diagram.png + :width: 400 + + +URL dell'istanza +---------------- + +Ciascuna istanza è accessibile tramite **uno specifico URL**, deciso dall'amministratore di sistema al momento dell'installazione. + +.. image:: urls.png + :width: 400 + + +Istanze nell'interfaccia web +---------------------------- + +L'interfaccia web di Sophon permette di **selezionare l'istanza** che si desidera usare inserendo il corrispondente URL. + +.. image:: choose.png diff --git a/report/source/1_user/2_concepts/1_instances/urls.png b/report/source/1_user/2_concepts/1_instances/urls.png new file mode 100644 index 0000000..03f62a0 --- /dev/null +++ b/report/source/1_user/2_concepts/1_instances/urls.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81424ecf1442787418deca201cca953b1c63fa80fff68c3637bcf52c27d8a091 +size 78677 diff --git a/report/source/1_user/2_concepts/2_users/creation.png b/report/source/1_user/2_concepts/2_users/creation.png new file mode 100644 index 0000000..c50c404 --- /dev/null +++ b/report/source/1_user/2_concepts/2_users/creation.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:15680a4cd5e988c57010e5b02cc281d6b7756fa371c46e50035365205a3f41dd +size 29373 diff --git a/report/source/1_user/2_concepts/2_users/diagram.png b/report/source/1_user/2_concepts/2_users/diagram.png new file mode 100644 index 0000000..1f98cc3 --- /dev/null +++ b/report/source/1_user/2_concepts/2_users/diagram.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b68b9844318fe1376043d846ce72729b1072cc0449a7680c556cade1d21dc63d +size 57146 diff --git a/report/source/1_user/2_concepts/2_users/index.rst b/report/source/1_user/2_concepts/2_users/index.rst new file mode 100644 index 0000000..189f3ec --- /dev/null +++ b/report/source/1_user/2_concepts/2_users/index.rst @@ -0,0 +1,58 @@ +Utente +====== + +Un *utente* è una entità che interagisce con una specifica istanza Sophon: ad esempio, un utente potrebbe essere una persona fisica, oppure potrebbe essere un software di automazione che si interfaccia con Sophon. + +.. image:: diagram.png + :width: 400 + + +Livelli di accesso +------------------ + +Un utente può avere uno dei seguenti *livelli di accesso*: + + +Superutente +^^^^^^^^^^^ + +Utente con accesso completo a ogni singola risorsa sull'istanza Sophon, tipicamente riservato per l'amministratore di sistema. + + +Utente +^^^^^^ + +Utente con permessi limitati alle risorse che ha creato o a cui è stato fornito accesso. + + +Ospite +^^^^^^ + +Utente che può visualizzare alcuni contenuti dell'istanza Sophon ma non può interagirci. + + +Credenziali di accesso +---------------------- + +Gli utenti di tipo :ref:`Utente` e :ref:`Superutente` devono identificarsi sull'istanza con le loro credenziali. + +Di default, le credenziali sono un **nome utente** e una **password**, ma è possibile che l'amministratore di sistema implementi un sistema diverso, ad esempio un sistema `Single Sign-On`_. + + +.. _Single Sign-On: https://it.wikipedia.org/wiki/Single_sign-on + + +Creazione di nuovi utenti +------------------------- + +In un':ref:`istanza` Sophon, la registrazione autonoma **non è permessa**: nuovi utenti possono essere creati esclusivamente da un :ref:`superutente` all'interno del pannello di amministrazione. + +.. image:: creation.png + + +Utenti nell'interfaccia web +--------------------------- + +Dopo aver selezionato un':ref:`istanza`, l'interfaccia web di Sophon permette di **effettuare l'accesso** come la tipologia di utente con la quale si intende utilizzare il servizio. + +.. image:: login.png diff --git a/report/source/1_user/2_concepts/2_users/login.png b/report/source/1_user/2_concepts/2_users/login.png new file mode 100644 index 0000000..8549c20 --- /dev/null +++ b/report/source/1_user/2_concepts/2_users/login.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:196420450f19e73fac5e8f2ce6c1862c66fe918f9e42adc128351d82f5ed9145 +size 90746 diff --git a/report/source/1_user/2_concepts/3_researchgroups/choose.png b/report/source/1_user/2_concepts/3_researchgroups/choose.png new file mode 100644 index 0000000..05b10db --- /dev/null +++ b/report/source/1_user/2_concepts/3_researchgroups/choose.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a1391d16432b6479288f756d4bc6bf0150f7cf8319bb65c44840e6ca0ff563b9 +size 56251 diff --git a/report/source/1_user/2_concepts/3_researchgroups/creation.png b/report/source/1_user/2_concepts/3_researchgroups/creation.png new file mode 100644 index 0000000..015baf0 --- /dev/null +++ b/report/source/1_user/2_concepts/3_researchgroups/creation.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1c55e19a3bd346d93ab74d1fa64c19640dda604edf85594cc294af5b70f9344b +size 29389 diff --git a/report/source/1_user/2_concepts/3_researchgroups/diagram.png b/report/source/1_user/2_concepts/3_researchgroups/diagram.png new file mode 100644 index 0000000..189e7c6 --- /dev/null +++ b/report/source/1_user/2_concepts/3_researchgroups/diagram.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:199492ba18145d93589f0f7f341a11b03a39e1b1c5e68ddd344fd44f3978e373 +size 75195 diff --git a/report/source/1_user/2_concepts/3_researchgroups/icons.png b/report/source/1_user/2_concepts/3_researchgroups/icons.png new file mode 100644 index 0000000..27741ca --- /dev/null +++ b/report/source/1_user/2_concepts/3_researchgroups/icons.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14dd8467d2cb74c628c84101452f943c2138821c755e72171914d31a5279948a +size 17782 diff --git a/report/source/1_user/2_concepts/3_researchgroups/index.rst b/report/source/1_user/2_concepts/3_researchgroups/index.rst new file mode 100644 index 0000000..79958d8 --- /dev/null +++ b/report/source/1_user/2_concepts/3_researchgroups/index.rst @@ -0,0 +1,69 @@ +Gruppo di ricerca +================= + +Un *gruppo di ricerca* rappresenta un insieme di utenti che collaborano su uno o più progetti. + +.. image:: diagram.png + :width: 400 + + +Membri e modalità di accesso +---------------------------- + +Gli utenti dell':ref:`istanza` possono diventare *membri* dei gruppi di ricerca, con una delle seguenti modalità selezionate nelle impostazioni del gruppo: + +- se il gruppo è *aperto*, allora qualsiasi utente può diventarne membro semplicemente **facendo richiesta** attraverso l'interfaccia web; + + .. image:: join_open.png + +- se il gruppo è in *modalità manuale*, allora nessun utente potrà richiedere di unirsi, e i membri saranno **selezionati manualmente** dal creatore del gruppo. + + .. image:: join_manual.png + +Nell'interfaccia web, i gruppi aperti sono marcati con l'icona di un **globo 🌐**, mentre i gruppi in modalità manuale sono marcati con l'icona di una **busta ✉️**. + +.. image:: icons.png + +In qualsiasi momento, i membri di un gruppo possono **lasciarlo** facendo richiesta attraverso l'interfaccia web. + + +Creazione di nuovi gruppi +------------------------- + +Qualsiasi :ref:`utente` può **creare** gruppi di ricerca dall'interfaccia web. + +.. image:: creation.png + + +Modifica di gruppi +------------------ + +Il creatore di un gruppo di ricerca è l'unico :ref:`utente` che può cambiarne **nome**, **descrizione**, **membri** e **modalità di accesso**. + +Lo *slug*, l'identificatore univoco del gruppo, non è modificabile successivamente alla creazione, in quanto è utilizzato all'interno degli URL, che devono essere immutabili. + + +Eliminazione di gruppi +---------------------- + +Il creatore di un gruppo è l'unico utente in grado di **cancellare** il gruppo che ha creato. + +.. warning:: + + L'eliminazione di un gruppo è un'operazione distruttiva non reversibile! + +.. hint:: + + Se si è i creatori di un gruppo, e si vuole trasferire il gruppo ad un altro utente, sarà necessario fare richiesta ad un :ref:`superutente` di cambiare il proprietario del gruppo all'interno del pannello di amministrazione. + +.. seealso:: + + :ref:`Conferma di eliminazione` + + +Gruppi nell'interfaccia web +--------------------------- + +Dopo aver effettuato l'accesso come :ref:`utente` o :ref:`ospite`, l'interfaccia utente di Sophon visualizza l'elenco di gruppi di ricerca disponibili nell':ref:`istanza`, permettendo agli utenti di unirsi ad essi, lasciarli, oppure eliminarli. + +.. image:: list.png diff --git a/report/source/1_user/2_concepts/3_researchgroups/join_manual.png b/report/source/1_user/2_concepts/3_researchgroups/join_manual.png new file mode 100644 index 0000000..bc576ba --- /dev/null +++ b/report/source/1_user/2_concepts/3_researchgroups/join_manual.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c116a160f21ebf9b3bd38c5775ebe442d1b97c9ff74f0dabd441b37036a234a1 +size 3388 diff --git a/report/source/1_user/2_concepts/3_researchgroups/join_open.png b/report/source/1_user/2_concepts/3_researchgroups/join_open.png new file mode 100644 index 0000000..a51955e --- /dev/null +++ b/report/source/1_user/2_concepts/3_researchgroups/join_open.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:40dd1d443c4215308de6baddaaae7b70c19174be02cfbd96ef24e135c7dbce1e +size 1104 diff --git a/report/source/1_user/2_concepts/3_researchgroups/list.png b/report/source/1_user/2_concepts/3_researchgroups/list.png new file mode 100644 index 0000000..05b10db --- /dev/null +++ b/report/source/1_user/2_concepts/3_researchgroups/list.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a1391d16432b6479288f756d4bc6bf0150f7cf8319bb65c44840e6ca0ff563b9 +size 56251 diff --git a/report/source/1_user/2_concepts/4_researchprojects/creation.png b/report/source/1_user/2_concepts/4_researchprojects/creation.png new file mode 100644 index 0000000..41d9f08 --- /dev/null +++ b/report/source/1_user/2_concepts/4_researchprojects/creation.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf7e7fa390ed404d420fa0d4214b2570661c41b79d8a6b541cb6a132574a2664 +size 22283 diff --git a/report/source/1_user/2_concepts/4_researchprojects/diagram.png b/report/source/1_user/2_concepts/4_researchprojects/diagram.png new file mode 100644 index 0000000..2407086 --- /dev/null +++ b/report/source/1_user/2_concepts/4_researchprojects/diagram.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b8a81e60a0aff1a91182ea7614fc782c89612a857f6234d12ad92e53ba83a25 +size 43109 diff --git a/report/source/1_user/2_concepts/4_researchprojects/icons.png b/report/source/1_user/2_concepts/4_researchprojects/icons.png new file mode 100644 index 0000000..104f914 --- /dev/null +++ b/report/source/1_user/2_concepts/4_researchprojects/icons.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:336394cc2cad31491f46144262c3f6a0c3ab74a5381e7dfdc5c9334283dbca28 +size 19620 diff --git a/report/source/1_user/2_concepts/4_researchprojects/index.rst b/report/source/1_user/2_concepts/4_researchprojects/index.rst new file mode 100644 index 0000000..aa09a7c --- /dev/null +++ b/report/source/1_user/2_concepts/4_researchprojects/index.rst @@ -0,0 +1,68 @@ +Progetto di ricerca +=================== + +Un *progetto di ricerca* rappresenta una **collezione di oggetti** relativa a un singolo argomento mantenuta da un :ref:`gruppo di ricerca`. + +.. image:: diagram.png + :width: 400 + + +Visibilità dei progetti +----------------------- + +I progetti hanno tre diverse impostazioni di visibilità che regolano chi può visualizzarne i contenuti: + +.. glossary:: + + Progetto privato + Il progetto è visibile solo ai membri del gruppo a cui appartiene il progetto. + + Progetto interno + Il progetto è visibile solo agli :term:`utenti` dell'istanza, e non agli :term:`ospiti`. + + Progetto pubblico + Il progetto è visibile a tutti. + +I progetti privati sono marcati con l'icona di un **lucchetto chiuso 🔒**, i progetti interni con l'icona di un **università 🏦** e i progetti pubblici con l'icona di un **globo 🌐**. + +.. image:: icons.png + + +Creazione di nuovi progetti +--------------------------- + +Qualsiasi *membro* di un :ref:`gruppo di ricerca` può creare nuovi progetti. + +.. image:: creation.png + + +Modifica di progetti +-------------------- + +Qualsiasi *membro* di un :ref:`gruppo di ricerca` può modificare **nome**, **descrizione** dei progetti al suo interno. + +Solo il *creatore del gruppo* può modificarne la **visibilità**, o **trasferire il progetto ad un altro gruppo**. + +Lo *slug*, l'identificatore univoco del progetto, non è modificabile successivamente alla creazione, in quanto è utilizzato all'interno degli URL, che devono essere immutabili. + + +Eliminazione di progetti +------------------------ + +Qualsiasi *membro* di un :ref:`gruppo di ricerca` può eliminare i progetti al suo interno. + +.. warning:: + + L'eliminazione di un progetto è un'operazione distruttiva non reversibile! + +.. seealso:: + + :ref:`Conferma di eliminazione` + + +Progetti nell'interfaccia web +----------------------------- + +Dopo aver selezionato un :ref:`gruppo di ricerca`, l'interfaccia web mostra i progetti visibili all':term:`utente` attuale, e gli permette di selezionarne uno oppure di eliminarli. + +.. image:: list.png \ No newline at end of file diff --git a/report/source/1_user/2_concepts/4_researchprojects/list.png b/report/source/1_user/2_concepts/4_researchprojects/list.png new file mode 100644 index 0000000..319070e --- /dev/null +++ b/report/source/1_user/2_concepts/4_researchprojects/list.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6483b51d1c4873afae208edcbc6cb5ba93686279a7f852c0043bebdc82574a7d +size 73160 diff --git a/report/source/1_user/2_concepts/5_notebooks/action_lock.png b/report/source/1_user/2_concepts/5_notebooks/action_lock.png new file mode 100644 index 0000000..741a9b6 --- /dev/null +++ b/report/source/1_user/2_concepts/5_notebooks/action_lock.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37b45dc7b65ca02b85d2452cba46e389951ef55ea3247a754e385991e278b545 +size 1276 diff --git a/report/source/1_user/2_concepts/5_notebooks/action_start.png b/report/source/1_user/2_concepts/5_notebooks/action_start.png new file mode 100644 index 0000000..ff7e861 --- /dev/null +++ b/report/source/1_user/2_concepts/5_notebooks/action_start.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ec2a115354ecc99bebebdc0d7d67b1f694b7cc5e56e584aebd1ac8bba670bb3 +size 1183 diff --git a/report/source/1_user/2_concepts/5_notebooks/action_stop.png b/report/source/1_user/2_concepts/5_notebooks/action_stop.png new file mode 100644 index 0000000..ac87f06 --- /dev/null +++ b/report/source/1_user/2_concepts/5_notebooks/action_stop.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd19689074b67f17f7bd33cee77bd44b07e74aa101e3ad585310a89301d06be5 +size 1196 diff --git a/report/source/1_user/2_concepts/5_notebooks/collaboration.png b/report/source/1_user/2_concepts/5_notebooks/collaboration.png new file mode 100644 index 0000000..2493ebd --- /dev/null +++ b/report/source/1_user/2_concepts/5_notebooks/collaboration.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9daec8f7992e33d6b461cade2597663b59d13fe4ca893056c4fe78c8f2ee1580 +size 8913 diff --git a/report/source/1_user/2_concepts/5_notebooks/connection.png b/report/source/1_user/2_concepts/5_notebooks/connection.png new file mode 100644 index 0000000..f7463e2 --- /dev/null +++ b/report/source/1_user/2_concepts/5_notebooks/connection.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd1f3621d290e61af55e3fe691bf13ed904d958881a98311c2e2c660d6d91ec8 +size 20190 diff --git a/report/source/1_user/2_concepts/5_notebooks/creation.png b/report/source/1_user/2_concepts/5_notebooks/creation.png new file mode 100644 index 0000000..aec9851 --- /dev/null +++ b/report/source/1_user/2_concepts/5_notebooks/creation.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:35666ce1b2defa280e20278ffd4852f64d33e0fd7be0f774cca4b1c8990f05f6 +size 17713 diff --git a/report/source/1_user/2_concepts/5_notebooks/detail.png b/report/source/1_user/2_concepts/5_notebooks/detail.png new file mode 100644 index 0000000..9cd5961 --- /dev/null +++ b/report/source/1_user/2_concepts/5_notebooks/detail.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0157ff01f724995744fff5ec1d79c74cedaa3419b7b5ec9254f594943868087 +size 79129 diff --git a/report/source/1_user/2_concepts/5_notebooks/diagram.png b/report/source/1_user/2_concepts/5_notebooks/diagram.png new file mode 100644 index 0000000..f42b004 --- /dev/null +++ b/report/source/1_user/2_concepts/5_notebooks/diagram.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dda7e7b44dd4e5a1d559b04606db9c532d9d6629fde52cf5269d4f5e2dd3faf3 +size 35047 diff --git a/report/source/1_user/2_concepts/5_notebooks/diagram_network.png b/report/source/1_user/2_concepts/5_notebooks/diagram_network.png new file mode 100644 index 0000000..d6dde10 --- /dev/null +++ b/report/source/1_user/2_concepts/5_notebooks/diagram_network.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51c74f085ad2de7f21b350bdf0cac3442f24ba2a97baab2dcbcae96a57fd7760 +size 43812 diff --git a/report/source/1_user/2_concepts/5_notebooks/index.rst b/report/source/1_user/2_concepts/5_notebooks/index.rst new file mode 100644 index 0000000..5197bb6 --- /dev/null +++ b/report/source/1_user/2_concepts/5_notebooks/index.rst @@ -0,0 +1,155 @@ +Notebook +======== + +Un *notebook* rappresenta una **postazione di lavoro** che può essere allegata ad un :ref:`progetto di ricerca`. + +.. image:: diagram.png + :width: 400 + + +Creazione di nuovi notebook +--------------------------- + +Qualsiasi **membro** di un :ref:`gruppo di ricerca` può creare nuovi notebook all'interno di uno dei progetti del gruppo a cui appartiene. + +.. image:: creation.png + +.. note:: + + Per motivi tecnici, i notebook non possono avere come slug ``backend``, ``frontend``, ``proxy``, ``api``, ``static`` e ``src``, oppure iniziare o terminare con un trattino ``-``. + + +Stato del notebook +------------------ + +Un notebook può essere *avviato* o *fermo* in base al suo stato di esecuzione sull':ref:`istanza` Sophon: + +- è *avviato* se sta venendo eseguito ed è accessibile; + + .. image:: status_stopped.png + :height: 40 + +- è *fermo* se non sta venendo eseguito o sta venendo preparato. + + .. image:: status_running.png + :height: 40 + +Alla creazione, un notebook è *fermo*. + + +Avviare un notebook +^^^^^^^^^^^^^^^^^^^ + +Un **membro** del :ref:`gruppo di ricerca` a cui appartiene il notebook può richiedere al server l'avvio di quest'ultimo, in modo da poterlo utilizzare successivamente. + +.. image:: action_start.png + + +Fermare un notebook +^^^^^^^^^^^^^^^^^^^ + +Un **membro** del :ref:`gruppo di ricerca` a cui appartiene il notebook può richiedere al server l'arresto di quest'ultimo, salvando i dati e interrompendo la sessione di lavoro attualmente in corso. + +.. image:: action_stop.png + +.. warning:: + + Se un notebook viene fermato durante un upload o download di file, essi risulteranno corrotti e saranno da ritrasferire. + + +Immagine del notebook +--------------------- + +In **fase di creazione** di un notebook, oppure mentre esso è **fermo**, è possibile selezionare un'*immagine*, ovvero il programma che sarà eseguito dal notebook all'avvio. + +Attualmente, l'unica immagine configurata è **Jupyter (Sophon)**, che esegue un server `Jupyter`_ con un'interfaccia `JupyterLab`_. + + +.. _Jupyter: https://jupyter.org/ +.. _JupyterLab: https://jupyterlab.readthedocs.io/en/stable/ + + +Collegarsi a un notebook +------------------------ + +I **membri** del :ref:`gruppo di ricerca` a cui appartiene il notebook possono connettersi ad un notebook **avviato** attraverso un URL segreto comunicatogli dall':ref:`istanza`. + +.. image:: connection.png + + +Utilizzo di un notebook +^^^^^^^^^^^^^^^^^^^^^^^ + +Una volta connessi ad un notebook, sarà visualizzato il programma eseguito dall'immagine selezionata. + +.. seealso:: + + Per informazioni su come usare JupyterLab, è possibile consultare l'apposita `documentazione `_. + + +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 diff --git a/report/source/1_user/2_concepts/5_notebooks/inside_the_lab.png b/report/source/1_user/2_concepts/5_notebooks/inside_the_lab.png new file mode 100644 index 0000000..9ab7022 --- /dev/null +++ b/report/source/1_user/2_concepts/5_notebooks/inside_the_lab.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd78b5c60796874aae09dc44a92dfb3377c460bd4a339e0b92dc3ff44ebfe705 +size 66942 diff --git a/docs/source/docs/1_sinossi/screenshot.png b/report/source/1_user/2_concepts/5_notebooks/list.png similarity index 100% rename from docs/source/docs/1_sinossi/screenshot.png rename to report/source/1_user/2_concepts/5_notebooks/list.png diff --git a/report/source/1_user/2_concepts/5_notebooks/locked.png b/report/source/1_user/2_concepts/5_notebooks/locked.png new file mode 100644 index 0000000..3b6686f --- /dev/null +++ b/report/source/1_user/2_concepts/5_notebooks/locked.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f78c111fc4acfb4cf277ab858071519594cdf0276903da20afcb102cf8578e6e +size 6765 diff --git a/report/source/1_user/2_concepts/5_notebooks/status_running.png b/report/source/1_user/2_concepts/5_notebooks/status_running.png new file mode 100644 index 0000000..7bfb253 --- /dev/null +++ b/report/source/1_user/2_concepts/5_notebooks/status_running.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:122a8955e24b22847ed34e23afd9f8d76a749e41318d0b56c6df71991992cfec +size 2234 diff --git a/report/source/1_user/2_concepts/5_notebooks/status_stopped.png b/report/source/1_user/2_concepts/5_notebooks/status_stopped.png new file mode 100644 index 0000000..e4b53ab --- /dev/null +++ b/report/source/1_user/2_concepts/5_notebooks/status_stopped.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:548af42920182fb1f71b89eb65ceaf296fc414ba69f6db7bdffc651294939d60 +size 2909 diff --git a/report/source/1_user/2_concepts/diagram_full.png b/report/source/1_user/2_concepts/diagram_full.png new file mode 100644 index 0000000..c855731 --- /dev/null +++ b/report/source/1_user/2_concepts/diagram_full.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:897969d6497c7b7f88b2b7de6a7a7e48a6362fe5f92b032b31a16f6d6dea21fe +size 155053 diff --git a/report/source/1_user/2_concepts/index.rst b/report/source/1_user/2_concepts/index.rst new file mode 100644 index 0000000..da12ac3 --- /dev/null +++ b/report/source/1_user/2_concepts/index.rst @@ -0,0 +1,15 @@ +I concetti +********** + +Questa sezione illustra i concetti chiave di Sophon e il loro funzionamento. + +.. toctree:: + :maxdepth: 1 + + 1_instances/index + 2_users/index + 3_researchgroups/index + 4_researchprojects/index + 5_notebooks/index + +.. image:: diagram_full.png \ No newline at end of file diff --git a/report/source/1_user/3_extras/confirm.png b/report/source/1_user/3_extras/confirm.png new file mode 100644 index 0000000..38d99f4 --- /dev/null +++ b/report/source/1_user/3_extras/confirm.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:118a138b62d2c6b223c2d215f54217e87f2d6b08cc4f9ac1549a4b0cb9b2d60b +size 1275 diff --git a/report/source/1_user/3_extras/index.rst b/report/source/1_user/3_extras/index.rst new file mode 100644 index 0000000..d44d019 --- /dev/null +++ b/report/source/1_user/3_extras/index.rst @@ -0,0 +1,72 @@ +Dettagli dell'interfaccia web +***************************** + +Sono elencate in questo capitolo alcuni dettagli interessanti relativi all'intera interfaccia web. + + +Markdown nelle descrizioni +========================== + +Le descrizioni dell':ref:`istanza`, del :ref:`gruppo di ricerca` selezionato e del :ref:`progetto di ricerca` selezionato sono interpretate dall'interfaccia web come `Markdown`_, un semplice e comune linguaggio di marcatura del testo con varie funzionalità che possono essere utili per descrivere l'entità in questione o lasciare messaggi agli altri collaboratori. + +Si fornisce un breve riassunto della sintassi di `Markdown`_. + +.. code-block:: markdown + + + + + # Parte + ## Capitolo + ### Sezione + #### Sottosezione + ##### Sottosottosezione + ###### Paragrafo + + + **grassetto** + *corsivo* + __sottolineato__ + `codice` + + + [testo](url) + + + ![alt](url) + + + | Riga 1 | Riga 2 | Riga 3 | + |--------|--------|--------| + | Cella | Cella | Cella | + | Cella | Cella | Cella | + + + ```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 + +

diff --git a/report/source/1_user/3_extras/members_list.png b/report/source/1_user/3_extras/members_list.png new file mode 100644 index 0000000..6c168f6 --- /dev/null +++ b/report/source/1_user/3_extras/members_list.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:223a669bacda4c0492a58d7eee5d6e22d832915c66116859eb8ca1df0b8fdff6 +size 6635 diff --git a/report/source/1_user/admin_login.png b/report/source/1_user/admin_login.png new file mode 100644 index 0000000..0b51e45 --- /dev/null +++ b/report/source/1_user/admin_login.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1e5c1c88b99011e1bf095b9136450d332a703421b9178e9af00f9f4edae977fe +size 7900 diff --git a/report/source/1_user/classic_notebook.png b/report/source/1_user/classic_notebook.png new file mode 100644 index 0000000..21809c0 --- /dev/null +++ b/report/source/1_user/classic_notebook.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f638971e3f0d515a7b6fcae26a524dfee928a577a52aa59ef58e32dbcee80486 +size 74345 diff --git a/report/source/1_user/screenshots/admin_page.png b/report/source/1_user/screenshots/admin_page.png new file mode 100644 index 0000000..8d88ef7 --- /dev/null +++ b/report/source/1_user/screenshots/admin_page.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:36b83f546246eb6a95242202d1337a64eaf1d698c3be7fbea57f8d397c6bfd56 +size 84223 diff --git a/report/source/2_admin/1_installation/1_requirements.rst b/report/source/2_admin/1_installation/1_requirements.rst new file mode 100644 index 0000000..4da19fd --- /dev/null +++ b/report/source/2_admin/1_installation/1_requirements.rst @@ -0,0 +1,21 @@ +Requisiti dell'host +=================== + +- Una connessione ad Internet (solo in fase di installazione) +- `GNU Wget`_ (solo in fase di installazione) +- Un nome di dominio +- Un webserver (ad esempio, `Apache HTTPd`_) +- Un certificato SSL valido *(opzionale, ma raccomandato)* +- `Docker Engine`_ +- `Docker Compose`_ + +.. hint:: + + È possibile ottenere gratuitamente un certificato SSL utilizzando `Letsencrypt`_! + + +.. _GNU Wget: https://www.gnu.org/software/wget/ +.. _Apache HTTPd: https://httpd.apache.org/ +.. _Docker Engine: https://docs.docker.com/engine/ +.. _Docker Compose: https://docs.docker.com/compose/ +.. _Letsencrypt: https://letsencrypt.org/ diff --git a/report/source/2_admin/1_installation/2_preparing_compose.rst b/report/source/2_admin/1_installation/2_preparing_compose.rst new file mode 100644 index 0000000..386cfd2 --- /dev/null +++ b/report/source/2_admin/1_installation/2_preparing_compose.rst @@ -0,0 +1,30 @@ +Preparazione di Docker Compose +============================== + +Come ``root``, si crei una nuova cartella sul proprio sistema operativo in cui archiviare le risorse relative a Sophon: + +.. code-block:: console + + root:~# mkdir -p /dock/sophon + +Successivamente, si scarichi il file ``docker-compose.yml`` all'interno della cartella dal repository di Sophon: + +.. code-block:: console + + root:~# cd /dock/sophon + + root:/dock/sophon# wget "https://raw.githubusercontent.com/Steffo99/sophon/main/docker-compose.yml" + --2021-11-02 18:03:05-- https://raw.githubusercontent.com/Steffo99/sophon/main/docker-compose.yml + SSL_INIT + Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt' + Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, + 185.199.109.133, 185.199.110.133, ... + Connecting to raw.githubusercontent.com (raw.githubusercontent.com) 185.199.108.133:443... + connected. + HTTP request sent, awaiting response... 200 OK + Length: 2957 (2.9K) [text/plain] + Saving to: ‘docker-compose.yml’ + + docker-compose.yml 100%[===================>] 2.89K --.-KB/s in 0s + + 2021-11-02 18:03:05 (48.0 MB/s) - ‘docker-compose.yml’ saved [2957/2957] diff --git a/report/source/2_admin/1_installation/3_configuring_dns.rst b/report/source/2_admin/1_installation/3_configuring_dns.rst new file mode 100644 index 0000000..db1113b --- /dev/null +++ b/report/source/2_admin/1_installation/3_configuring_dns.rst @@ -0,0 +1,17 @@ +Configurazione DNS +================== + +Si scelga il dominio (o sottodominio) sul quale si vuole che Sophon sia accessibile e si aggiungano i seguenti record DNS, sostituendo il dominio ``ilmiosophon.it`` con il proprio nome di dominio, e gli indirizzi IPv4 e IPv6 del server al posto di `0.0.0.0` e `1234::1234`: + +.. code-block:: dns + + *.ilmiosophon.it 1800 IN A 0.0.0.0 + *.ilmiosophon.it 1800 IN AAAA 1234::1234 + ilmiosophon.it 1800 IN A 0.0.0.0 + ilmiosophon.it 1800 IN AAAA 1234::1234 + +Sophon sarà quindi accessibile ai seguenti indirizzi: + +- l'interfaccia web al dominio base (``https://ilmiosophon.it/``); +- l'API al dominio base prefisso con ``api.`` (``https://api.ilmiosophon.it/``); +- i notebook al dominio base prefissi con lo slug del notebook (``https://ilmionotebook.ilmiosophon.it/``). diff --git a/report/source/2_admin/1_installation/4_configuring_compose.rst b/report/source/2_admin/1_installation/4_configuring_compose.rst new file mode 100644 index 0000000..7a964c1 --- /dev/null +++ b/report/source/2_admin/1_installation/4_configuring_compose.rst @@ -0,0 +1,222 @@ +Configurazione ``docker-compose.yml`` +===================================== + +Si configuri con l'editor di testo preferito il file ``docker-compose.yml`` con le impostazioni desiderate. + +.. code-block:: console + + root:/dock/sophon# open docker-compose.yml + +In particolare, tutte le impostazioni precedute da ``# INSTALL`` vanno obbligatoriamente modificate. + + +``DJANGO_SECRET_KEY`` +--------------------- + +Specifica la chiave segreta da usare per i cookie di sessione. + +.. code-block:: yaml + + - DJANGO_SECRET_KEY=do-not-use-this-key-in-production-or-you-will-get-hacked + +.. tip:: + + Un modo facile per impostare la chiave è premere velocemente tasti a caso sulla tastiera! + +.. note:: + + Cambiare la chiave segreta una volta installato Sophon invaliderà tutti gli accessi effettuati dagli utenti. + +.. warning:: + + La chiave segreta è un dato estremamente riservato: chiunque sia a conoscenza della chiave segreta potrà effettuare l'accesso come qualsiasi utente! + +.. seealso:: + + `SECRET_KEY `_ 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 `_ 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 `_ 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 `_ 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 `_ 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. \ No newline at end of file diff --git a/report/source/2_admin/1_installation/5_pulling_images.rst b/report/source/2_admin/1_installation/5_pulling_images.rst new file mode 100644 index 0000000..6eff74c --- /dev/null +++ b/report/source/2_admin/1_installation/5_pulling_images.rst @@ -0,0 +1,48 @@ +Download delle immagini Docker +============================== + +Si utilizzi `Docker Compose`_ per scaricare le `immagini`_ Docker necessarie all'avvio di Sophon: + +.. code-block:: console + + root:/dock/sophon# docker compose pull + [+] Running 4/4 + ⠿ proxy Pulled 1.5s + ⠿ frontend Pulled 1.4s + ⠿ db Pulled 1.9s + ⠿ backend Pulled 1.6s + +Inoltre, si scarichi manualmente l':ref:`immagine del Notebook` che può essere avviata da Sophon: + +.. code-block:: console + + root:/dock/sophon# docker image pull "ghcr.io/steffo99/sophon-jupyter:latest" + latest: Pulling from steffo99/sophon-jupyter + 7b1a6ab2e44d: Already exists + 578d7ac380c6: Pull complete + 37f1e0b584f6: Pull complete + 3c7282703390: Pull complete + b38aa558f711: Pull complete + 1412103d568f: Pull complete + 67419a9a821e: Pull complete + 37e6cc015184: Pull complete + 7d9316e2b57c: Pull complete + a7f024508c72: Pull complete + f3eae3c301a1: Pull complete + d3e2107efade: Pull complete + d94bc6f8f069: Pull complete + 1e1dc3e818ad: Pull complete + c975ee664182: Pull complete + 101cfcc0e15b: Pull complete + bf991a0d7538: Pull complete + 4c044af18c7e: Pull complete + 605d8c6e8eba: Pull complete + ed06f2ae4a88: Pull complete + ed8b1c841d10: Pull complete + 468fe9a390ae: Pull complete + Digest: sha256:5d42e5e40e406130c688914d6a58aa94769eab03620b53e0fd409a7fb2682a01 + Status: Downloaded newer image for ghcr.io/steffo99/sophon-jupyter:latest + ghcr.io/steffo99/sophon-jupyter:latest + +.. _Docker Compose: https://docs.docker.com/compose/ +.. _immagini: https://docs.docker.com/engine/reference/commandline/images/ diff --git a/report/source/2_admin/1_installation/6_starting_sophon.rst b/report/source/2_admin/1_installation/6_starting_sophon.rst new file mode 100644 index 0000000..aec0f13 --- /dev/null +++ b/report/source/2_admin/1_installation/6_starting_sophon.rst @@ -0,0 +1,22 @@ +Avvio di Sophon +=============== + +Si utilizzi `Docker Compose`_ per eseguire le `immagini`_ di Sophon precedentemente scaricate: + +.. code-block:: console + + root:/dock/sophon# docker compose up -d + [+] Running 4/4 + ⠿ Container sophon-db-1 Started 11.3s + ⠿ Container sophon-frontend-1 Started 11.7s + ⠿ Container sophon-backend-1 Started 10.1s + ⠿ Container sophon-proxy-1 Started 11.5s + +Si verifichi che i container si siano avviati correttamente con: + +.. code-block:: console + + root:/dock/sophon# docker compose logs + +.. _Docker Compose: https://docs.docker.com/compose/ +.. _immagini: https://docs.docker.com/engine/reference/commandline/images/ diff --git a/report/source/2_admin/1_installation/7_host_reverse_proxy.rst b/report/source/2_admin/1_installation/7_host_reverse_proxy.rst new file mode 100644 index 0000000..a473ee3 --- /dev/null +++ b/report/source/2_admin/1_installation/7_host_reverse_proxy.rst @@ -0,0 +1,62 @@ +Configurazione del webserver dell'host +====================================== + +Si configuri il webserver dell'host per inoltrare tutto il traffico dalla porta 443 (o 80, se si è selezionato ``http`` in :ref:`\`\`DJANGO_PROXY_PROTOCOL\`\``) alla porta locale 30033. + +Sono allegate le istruzioni per il webserver `Apache HTTPd`_; possono essere però adattate se si vuole usare un webserver diverso, come `NGINX`_ o `caddy`_. + +.. _Apache HTTPd: https://httpd.apache.org/ +.. _nginx: https://www.nginx.com/ +.. _caddy: https://caddyserver.com/ + + +Con Apache HTTPd +---------------- + +Ci si assicuri che `mod_rewrite`_, `mod_proxy`_, `mod_proxy_http`_ e `mod_proxy_wstunnel`_ siano attivati. + +Si aggiungano i seguenti ``VirtualHost`` alla configurazione: + +.. code-block:: apacheconf + + + ServerName "ilmiosophon.it" + ServerAlias "*.ilmiosophon.it" + + RewriteEngine On + RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L] + + +.. code-block:: apacheconf + + + 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" + + +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 diff --git a/report/source/2_admin/1_installation/8_final_check.rst b/report/source/2_admin/1_installation/8_final_check.rst new file mode 100644 index 0000000..c90d25d --- /dev/null +++ b/report/source/2_admin/1_installation/8_final_check.rst @@ -0,0 +1,4 @@ +Verificare il funzionamento +=========================== + +Se tutto è stato configurato correttamente, l'interfaccia web Sophon dovrebbe essere raggiungibile al dominio selezionato (``https://ilmiosophon.it``), e dovrebbe essere possibile effettuare il login con le credenziali configurate del primo :ref:`superutente`. diff --git a/report/source/2_admin/1_installation/index.rst b/report/source/2_admin/1_installation/index.rst new file mode 100644 index 0000000..595d46b --- /dev/null +++ b/report/source/2_admin/1_installation/index.rst @@ -0,0 +1,18 @@ +Installazione +************* + +Questo capitolo fornisce le informazioni per l'installazione di Sophon su un server Linux. + +.. toctree:: + :numbered: + :maxdepth: 1 + + 1_requirements + 2_preparing_compose + 3_configuring_dns + 4_configuring_compose + 5_pulling_images + 6_starting_sophon + 7_host_reverse_proxy + 8_final_check + diff --git a/report/source/2_admin/2_administration/1_admin_panel.rst b/report/source/2_admin/2_administration/1_admin_panel.rst new file mode 100644 index 0000000..5e67b83 --- /dev/null +++ b/report/source/2_admin/2_administration/1_admin_panel.rst @@ -0,0 +1,32 @@ +Pannello di amministrazione +=========================== + +Sophon include un pannello di amministrazione, accessibile premendo *Go to the admin page* sulla schermata di login, oppure visitando l'URL ``api.DOMINIO/admin``. + +.. image:: admin_where.png + + +Effettuare l'accesso +-------------------- + +Per utilizzare il pannello di amministrazione è necessario inserire le credenziali di un :ref:`superutente`. + +.. image:: admin_login.png + + +La schermata principale +----------------------- + +Nella schermata principale del pannello di amministrazione è visibile l'elenco di tutti i tipi di entità gestite da Django, assieme ad uno storico delle ultime operazioni effettuate dal pannello su di esse. + +.. image:: admin_home.png + +È possibile cliccare sul collegamento *Add* di fianco ad un tipo di entità per **crearne** una nuova di quel tipo, oppure il collegamento *Change* per **visualizzare**, **modificare** ed **eliminare** tutte le entità già esistenti di quel tipo. + + +La barra del titolo +------------------- + +Tutte le pagine includono in cima la **barra del titolo**, che permette al :ref:`superutente` attualmente collegato di **cambiare la propria password** o effettuare la **disconnessione** dal pannello. + +.. image:: topright.png diff --git a/report/source/2_admin/2_administration/2_entities.rst b/report/source/2_admin/2_administration/2_entities.rst new file mode 100644 index 0000000..e44b28c --- /dev/null +++ b/report/source/2_admin/2_administration/2_entities.rst @@ -0,0 +1,112 @@ +Tipi di risorse +=============== + +Tokens +------ + +Contiene l'elenco di tutti i token di sessione usati per l'autenticazione tra l'API e l'interfaccia web di Sophon. + +È possibile modificarli per **cambiare l'utente connesso** ad una certa sessione, oppure eliminarli per **forzare la disconnessione** di determinate sessioni. + +.. note:: + + In seguito ad una disconnessione forzata, l'utente riscontrerà errori "non autorizzato" sull'interfaccia web fino ad un aggiornamento della pagina o logout manuale. + +.. image:: token_list.png + :scale: 50% + +.. image:: token_detail.png + :scale: 50% + + +Users +----- + +Contiene l'elenco di tutti gli utenti registrati su Sophon. + +In questa pagina è possibile la :ref:`creazione di nuovi utenti`, così come il **cambio di password**, l'**assegnazione di privilegi** di :ref:`superutente` e la **disattivazione degli utenti**. + +.. note:: + + I superutenti devono avere sia *staff status* sia *superuser status* attivi per poter utilizzare il pannello di amministrazione. + +.. image:: user_list.png + :scale: 50% + +.. image:: user_detail.png + :scale: 50% + + +Research groups +--------------- + +Contiene l'elenco di tutti i gruppi di ricerca creati su Sophon. + +Dal pannello di amministrazione è possibile effettuare modifiche ed eliminazioni **ignorando i permessi normalmente richiesti** per farlo e **trasferire la proprietà** di un gruppo da un utente all'altro. + +.. image:: researchgroup_list.png + :scale: 50% + +.. image:: researchgroup_detail.png + :scale: 50% + + +Sophon instance details +----------------------- + +Contiene un'entità speciale che controlla l'**aspetto** dell':ref:`istanza`. + +Modificandola, è possibile personalizzare: + +- il **nome** dell':ref:`istanza`, che verrà visualizzato come titolo dell'interfaccia web; + + .. image:: custom_title.png + +- la **descrizione** dell':ref:`istanza`, visualizzata all'interno del riquadro "A proposito dell'istanza"; + + .. image:: custom_description.png + +- il **tema colori** dell':ref:`istanza`, applicato all'interfaccia web una volta che un':ref:`istanza` è stata selezionata. + + .. image:: theme_sophon.png + :width: 240 + .. image:: theme_royalblue.png + :width: 240 + .. image:: theme_amber.png + :width: 240 + .. image:: theme_paper.png + :width: 240 + .. image:: theme_hacker.png + :width: 240 + + +Notebooks +--------- + +Contiene l'elenco di tutti i :ref:`notebook` creati su Sophon. + +Oltre ad alterare le entità **ignorando i permessi**, è possibile vedere alcuni parametri tecnici, come l'ID del container Docker a cui è associato il notebook, oppure la porta o l'URL a cui è accessibile il notebook dal proxy. + +.. warning:: + + Modificare *slug*, *container ID*, *local port number* o *internal URL* mentre il :ref:`notebook` è avviato renderà potenzialmente la connessione e l'arresto del notebook! + +.. image:: notebook_list.png + :scale: 50% + +.. image:: notebook_detail.png + :scale: 50% + + +Research projects +----------------- + +Contiene l'elenco di tutti i progetti di ricerca creati su Sophon. + +Oltre ad alterare le entità **ignorando i permessi**, è possibile **trasferire un progetto** da un gruppo a un altro. + +.. image:: researchproject_list.png + :scale: 50% + +.. image:: researchproject_detail.png + :scale: 50% diff --git a/report/source/2_admin/2_administration/admin_home.png b/report/source/2_admin/2_administration/admin_home.png new file mode 100644 index 0000000..fd88187 --- /dev/null +++ b/report/source/2_admin/2_administration/admin_home.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:489926d48ebe3e5cc917db3fc1527e34743f83774df34191e2a000d928759056 +size 69231 diff --git a/report/source/2_admin/2_administration/admin_login.png b/report/source/2_admin/2_administration/admin_login.png new file mode 100644 index 0000000..ece35e9 --- /dev/null +++ b/report/source/2_admin/2_administration/admin_login.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f1be89adc8338958bacff6ebe3c60170550bbe2978d2bf38376391e68bf84f0 +size 7842 diff --git a/report/source/2_admin/2_administration/admin_where.png b/report/source/2_admin/2_administration/admin_where.png new file mode 100644 index 0000000..6e8240f --- /dev/null +++ b/report/source/2_admin/2_administration/admin_where.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc776881546857ee1492b5db682772350d654d673bac544fde21e9b963b67c02 +size 26311 diff --git a/report/source/2_admin/2_administration/custom_description.png b/report/source/2_admin/2_administration/custom_description.png new file mode 100644 index 0000000..c60d183 --- /dev/null +++ b/report/source/2_admin/2_administration/custom_description.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd836dbca80ebf6276dcc78bc57af6ab52469c0b6530fc059d0c15a2e68263ff +size 10769 diff --git a/report/source/2_admin/2_administration/custom_title.png b/report/source/2_admin/2_administration/custom_title.png new file mode 100644 index 0000000..8b063b4 --- /dev/null +++ b/report/source/2_admin/2_administration/custom_title.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:694b3d936312e51d3c4d3f74d9aca45c9eed8e60d1600020fd42b93081c6d509 +size 4046 diff --git a/report/source/2_admin/2_administration/customization.png b/report/source/2_admin/2_administration/customization.png new file mode 100644 index 0000000..b97b9c7 --- /dev/null +++ b/report/source/2_admin/2_administration/customization.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:42ac7a211eba5b76dc7f7d95a1e6544ed460f8efe1049a0fe9377dbc77765f72 +size 32753 diff --git a/report/source/2_admin/2_administration/index.rst b/report/source/2_admin/2_administration/index.rst new file mode 100644 index 0000000..fdcb0d7 --- /dev/null +++ b/report/source/2_admin/2_administration/index.rst @@ -0,0 +1,9 @@ +Amministrazione +*************** + +Questo capitolo fornisce informazioni su come amministrare un':ref:`istanza` Sophon. + +.. toctree:: + + 1_admin_panel + 2_entities \ No newline at end of file diff --git a/report/source/2_admin/2_administration/notebook_detail.png b/report/source/2_admin/2_administration/notebook_detail.png new file mode 100644 index 0000000..1c2a526 --- /dev/null +++ b/report/source/2_admin/2_administration/notebook_detail.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd4ca44c61e7ac60541569ccbbb4ada8d577cf2c07a6bc9b8d208417d5c066e4 +size 63910 diff --git a/report/source/2_admin/2_administration/notebook_list.png b/report/source/2_admin/2_administration/notebook_list.png new file mode 100644 index 0000000..69cf025 --- /dev/null +++ b/report/source/2_admin/2_administration/notebook_list.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d82d22e5e270165875006f6b764f4f6eeeba49f9ee627919c48bd1b38f778f9 +size 34941 diff --git a/report/source/2_admin/2_administration/researchgroup_detail.png b/report/source/2_admin/2_administration/researchgroup_detail.png new file mode 100644 index 0000000..f10224c --- /dev/null +++ b/report/source/2_admin/2_administration/researchgroup_detail.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:addbd193f8f103711a5c07f8782d58d7412d31eaf8efdbea35dc88635af340fb +size 46809 diff --git a/report/source/2_admin/2_administration/researchgroup_list.png b/report/source/2_admin/2_administration/researchgroup_list.png new file mode 100644 index 0000000..a95d031 --- /dev/null +++ b/report/source/2_admin/2_administration/researchgroup_list.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:906cae69844692f8196aaa10e07768e52af5d0c1eb440b4e3deb5466fa6329b5 +size 26709 diff --git a/report/source/2_admin/2_administration/researchproject_detail.png b/report/source/2_admin/2_administration/researchproject_detail.png new file mode 100644 index 0000000..e7b234f --- /dev/null +++ b/report/source/2_admin/2_administration/researchproject_detail.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:91b8edb0265610bc2e26c9fdd6aa638f517219a6fc276ece7ce597832f765eba +size 43098 diff --git a/report/source/2_admin/2_administration/researchproject_list.png b/report/source/2_admin/2_administration/researchproject_list.png new file mode 100644 index 0000000..dc84908 --- /dev/null +++ b/report/source/2_admin/2_administration/researchproject_list.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e66fe36471b5e6278ef731d281be7ef03b403f6688effe5eb9db04516d9fe12 +size 23283 diff --git a/report/source/2_admin/2_administration/theme_amber.png b/report/source/2_admin/2_administration/theme_amber.png new file mode 100644 index 0000000..e718dbe --- /dev/null +++ b/report/source/2_admin/2_administration/theme_amber.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:29a83246fdbde1f4da79079941eff2f6787634aeb0e9ca6890e3869637033950 +size 87539 diff --git a/report/source/2_admin/2_administration/theme_hacker.png b/report/source/2_admin/2_administration/theme_hacker.png new file mode 100644 index 0000000..f866aa3 --- /dev/null +++ b/report/source/2_admin/2_administration/theme_hacker.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30280a0d7cb11872d53808b23321a6dceda327846df916499cb0686d8fa18ad7 +size 92360 diff --git a/report/source/2_admin/2_administration/theme_paper.png b/report/source/2_admin/2_administration/theme_paper.png new file mode 100644 index 0000000..9ddc34a --- /dev/null +++ b/report/source/2_admin/2_administration/theme_paper.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1e9387183c87e6e975e3b29f8c20c2cb54a0d8ccde92283dc879e7e27657d1cb +size 93038 diff --git a/report/source/2_admin/2_administration/theme_royalblue.png b/report/source/2_admin/2_administration/theme_royalblue.png new file mode 100644 index 0000000..389cc0a --- /dev/null +++ b/report/source/2_admin/2_administration/theme_royalblue.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cb4732d43c7beaae086b3706aee975630368c89dbb40e5c443741cc1a118d097 +size 89961 diff --git a/report/source/2_admin/2_administration/theme_sophon.png b/report/source/2_admin/2_administration/theme_sophon.png new file mode 100644 index 0000000..8549c20 --- /dev/null +++ b/report/source/2_admin/2_administration/theme_sophon.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:196420450f19e73fac5e8f2ce6c1862c66fe918f9e42adc128351d82f5ed9145 +size 90746 diff --git a/report/source/2_admin/2_administration/token_detail.png b/report/source/2_admin/2_administration/token_detail.png new file mode 100644 index 0000000..42ec6a3 --- /dev/null +++ b/report/source/2_admin/2_administration/token_detail.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ea1c2d28d70d53cec0aded395d24eaaabad99f1dbe5426d086a1b1f1eb3b68e +size 11632 diff --git a/report/source/2_admin/2_administration/token_list.png b/report/source/2_admin/2_administration/token_list.png new file mode 100644 index 0000000..de348f2 --- /dev/null +++ b/report/source/2_admin/2_administration/token_list.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de32b22e21d78beb49924a804897bac93699fbbf9d5d81af83051fa0349cf4d5 +size 19474 diff --git a/report/source/2_admin/2_administration/topright.png b/report/source/2_admin/2_administration/topright.png new file mode 100644 index 0000000..ec306de --- /dev/null +++ b/report/source/2_admin/2_administration/topright.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0db77ac5563a6a4d5f070504db8c1935d854331d8d72849e55775a3ddc94271f +size 2915 diff --git a/report/source/2_admin/2_administration/user_detail.png b/report/source/2_admin/2_administration/user_detail.png new file mode 100644 index 0000000..129f98a --- /dev/null +++ b/report/source/2_admin/2_administration/user_detail.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:230cd2e5336de82b35c91144b86dfe17ab56436d5b24551422478bea05363399 +size 43813 diff --git a/report/source/2_admin/2_administration/user_list.png b/report/source/2_admin/2_administration/user_list.png new file mode 100644 index 0000000..32063a0 --- /dev/null +++ b/report/source/2_admin/2_administration/user_list.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eea11c7bdf759f791596c31b81119cf874d7be544f5f8b0a9c1ab15299c85c1e +size 28944 diff --git a/report/source/2_admin/3_update/index.rst b/report/source/2_admin/3_update/index.rst new file mode 100644 index 0000000..d66311d --- /dev/null +++ b/report/source/2_admin/3_update/index.rst @@ -0,0 +1,21 @@ +Aggiornamento +************* + +Per aggiornare Sophon, è sufficiente usare `Docker Compose`_ per scaricare le immagini aggiornate e riavviare i container del software. + +.. code-block:: console + + root:/dock/sophon# docker compose down + root:/dock/sophon# docker compose pull + root:/dock/sophon# docker compose up -d + +.. warning:: + + In seguito ad un aggiornamento o un riavvio, alcuni Notebook potrebbero essere **irraggiungibili dal proxy**. + + In tal caso, sarà sufficiente **fermarli** e **riavviarli** dall'interfaccia web. + + Non si verificherà alcuna perdita di dati! + + +.. _Docker Compose: https://docs.docker.com/compose/ diff --git a/report/source/2_admin/4_uninstallation/index.rst b/report/source/2_admin/4_uninstallation/index.rst new file mode 100644 index 0000000..e96aed7 --- /dev/null +++ b/report/source/2_admin/4_uninstallation/index.rst @@ -0,0 +1,27 @@ +Disinstallazione +**************** + +Per rimuovere completamente Sophon, è necessario innanzitutto arrestare i container del software principale: + +.. code-block:: console + + root:/dock/sophon# docker compose down + +In seguito, è necessario arrestare tutti i container dei notebook ancora avviati: + +.. code-block:: console + + root:/dock/sophon# docker container ls + c160ea085fe1 steffo45/jupyterlab-docker-sophon "tini -g -- start-no…" 23 hours ago Up 23 hours sophon-container-my-first-notebook + 0892874ea0d5 ghcr.io/steffo99/sophon-jupyter "tini -g -- start-no…" 3 minutes ago Up 3 minutes (healthy) sophon-container-normal-slug + root:/dock/sophon# docker container rm --force c160ea085fe1 0892874ea0d5 + +Infine sarà possibile liberare lo spazio occupato dalle risorse Docker di Sophon: + +.. code-block:: console + + root:/dock/sophon# docker compose down -v + root:/dock/sophon# docker volume prune + root:/dock/sophon# docker container prune + root:/dock/sophon# docker network prune + root:/dock/sophon# docker image prune diff --git a/report/source/3_dev/1_tools/index.rst b/report/source/3_dev/1_tools/index.rst new file mode 100644 index 0000000..f5ab86d --- /dev/null +++ b/report/source/3_dev/1_tools/index.rst @@ -0,0 +1,40 @@ +Strumenti usati per lo sviluppo +******************************* + +Per sviluppare Sophon sono usati i seguenti strumenti: + +- `IntelliJ IDEA Ultimate`_, un IDE multilinguaggio, con i seguenti plugin: + - Python + - Poetry + - ReStructuredText + - Node.JS + - JavaScript and TypeScript + - CSS + - Git + - Docker + +- `Git`_, uno strumento di controllo versione; + - `GitHub`_, un host per repository `Git`_; + - `GitHub Issues`_, un issue tracker integrato in `GitHub`_; + - `GitHub Actions`_, un sistema di `Continuous Integration`_ e `Continuous Deployment`_ integrato in `GitHub`_; + - `GitHub Containers`_, un registro di container Docker integrato in `GitHub`_; + - `CodeQL`_, un tool di analisi statica integrato in `GitHub`_; + - `Dependabot`_, un tool di analisi delle dipendenze integrato in `GitHub`_; + +- `Sphinx`_, uno strumento per la creazione di documentazione. + +.. _IntelliJ IDEA Ultimate: https://www.jetbrains.com/idea/ +.. _Git: https://git-scm.com/ +.. _GitHub: https://github.com/ +.. _GitHub Issues: https://github.com/features/issues/ +.. _GitHub Actions: https://github.com/features/actions +.. _Continuous Integration: https://it.wikipedia.org/wiki/Integrazione_continua +.. _Continuous Deployment: https://en.wikipedia.org/wiki/Continuous_deployment +.. _CodeQL: https://codeql.github.com/ +.. _GitHub Containers: https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry +.. _Sphinx: https://www.sphinx-doc.org/ +.. _Dependabot: https://dependabot.com/ + +.. seealso:: + + Nel capitolo successivo sono descritte le tecnologie utilizzate all'interno di Sophon. diff --git a/report/source/3_dev/2_structure/1_backend/1_techstack.rst b/report/source/3_dev/2_structure/1_backend/1_techstack.rst new file mode 100644 index 0000000..a9477c4 --- /dev/null +++ b/report/source/3_dev/2_structure/1_backend/1_techstack.rst @@ -0,0 +1,16 @@ +Librerie e tecnologie utilizzate +-------------------------------- + +.. note:: + + Sono elencate solo le principali librerie utilizzate; dipendenze e librerie minori non sono specificate, ma sono visibili all'interno del file ``poetry.lock``. + +- Il linguaggio di programmazione `Python `_ + - Il gestore di dipendenze `Poetry `_ + - Il framework web `Django `_ + - L'estensione per Django `Django REST Framework `_ + - L'estensione per Django `Django CORS Headers `_ + - L'adattatore database per PostgreSQL `Psycopg `_ + - Il `Docker SDK for Python `_ + - Il server web `Gunicorn `_ + - L'utilità `lazy-object-proxy `_ diff --git a/report/source/3_dev/2_structure/1_backend/2_sophon.rst b/report/source/3_dev/2_structure/1_backend/2_sophon.rst new file mode 100644 index 0000000..db9b562 --- /dev/null +++ b/report/source/3_dev/2_structure/1_backend/2_sophon.rst @@ -0,0 +1,89 @@ +Il progetto sophon +------------------ +.. default-domain:: py +.. default-role:: obj +.. module:: sophon + +Il progetto Django Sophon aggiunge varie funzionalità al template base dei progetti Django. + + +Pagina di amministrazione personalizzata +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. module:: sophon.admin + +La pagina di amministrazione viene personalizzata con la classe `SophonAdminSite`, che modifica alcuni parametri della classe base. + +Inoltre, il template predefinito viene sovrascritto da quello all'interno del file ``templates/admin/base.html``, che sostituisce il foglio di stile con uno personalizzato per Sophon. + +.. class:: SophonAdminSite(django.contrib.admin.AdminSite) + + .. attribute:: site_header = "Sophon Server Administration" + + Il nome della pagina nell'header viene modificato a *Sophon Server Administration*. + + .. attribute:: site_title = "Sophon Server Administration" + + Il titolo della pagina nell'header viene anch'esso modificato a *Sophon Server Administration*. + + .. attribute:: site_url = None + + Il collegamento *View Site* viene rimosso, in quanto è possibile accedere all'interfaccia web di Sophon da più domini contemporaneamente. + + .. attribute:: index_title = "Resources Administration" + + Il titolo dell'indice viene modificato a *Resources Administration*. + +.. class:: SophonAdminConfig(django.contrib.admin.apps.AdminConfig) + + .. attribute:: default_site = "sophon.admin.SophonAdminSite" + + `.SophonAdminSite` è selezionata come classe predefinita per il sito di amministrazione. + + +Impostazioni dinamiche +^^^^^^^^^^^^^^^^^^^^^^ +.. module:: sophon.settings + +Il file di impostazioni viene modificato per **permettere la configurazione attraverso variabili di ambiente** invece che attraverso il file ``settings.py``, rendendo il deployment con Docker molto più semplice. + +.. code-block:: python + + try: + DATABASE_ENGINE = os.environ["DJANGO_DATABASE_ENGINE"] + except KeyError: + log.warning("DJANGO_DATABASE_ENGINE was not set, defaulting to PostgreSQL") + DATABASE_ENGINE = "django.db.backends.postgresql" + log.debug(f"{DATABASE_ENGINE = }") + +Inoltre, viene configurato il modulo `logging` per emettere testo colorato di più facile comprensione usando il package `coloredlogs`. + +.. code-block:: python + + "detail": { + "()": coloredlogs.ColoredFormatter, + "format": "{asctime:>19} | {name:<24} | {levelname:>8} | {message}", + "style": "{", + } + + +Autenticazione migliorata +^^^^^^^^^^^^^^^^^^^^^^^^^ +.. module:: sophon.auth1 + +La classe `rest_framework.authentication.TokenAuthentication` viene modificata per ottenere un comportamento conforme agli standard del web. + +.. class:: BearerTokenAuthentication(rest_framework.authentication.TokenAuthentication) + + .. attribute:: keyword = "Bearer" + + Si configura `rest_framework` per accettare header di autenticazione nella forma ``Bearer ``, invece che ``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. diff --git a/report/source/3_dev/2_structure/1_backend/3_core.rst b/report/source/3_dev/2_structure/1_backend/3_core.rst new file mode 100644 index 0000000..17d2c55 --- /dev/null +++ b/report/source/3_dev/2_structure/1_backend/3_core.rst @@ -0,0 +1,333 @@ +L'app sophon.core +----------------- +.. default-domain:: py +.. default-role:: obj +.. module:: sophon.core + +L'app `sophon.core` è l'app principale del progetto, e non può essere disattivata, in quanto dipendenza obbligatoria di tutte le altre app. + + +Aggiunta di un nuovo comando di gestione +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. module:: sophon.core.management.commands.initsuperuser + +Per permettere l'integrazione la creazione automatica del primo :ref:`superutente` quando Sophon viene eseguito da Docker, viene introdotto dall'app il comando di gestione ``initsuperuser``. + +.. class:: Command + + Questo comando crea automaticamente un :ref:`superutente` con le credenziali specificate in :ref:`\`\`DJANGO_SU_USERNAME\`\``, :ref:`\`\`DJANGO_SU_EMAIL\`\`` e :ref:`\`\`DJANGO_SU_PASSWORD\`\``. + + +Modello base astratto +^^^^^^^^^^^^^^^^^^^^^ +.. module:: sophon.core.models + +Viene estesa la classe astratta `django.db.models.Model` con funzioni per stabilire il livello di accesso di un utente all'oggetto e per generare automaticamente i `rest_framework.serializers.ModelSerializer` in base al livello di accesso. + +.. class:: SophonModel(django.db.models.Model) + + .. method:: can_edit(self, user: django.contrib.auth.models.User) -> bool + :abstractmethod: + + Controlla se un utente può modificare l'oggetto attuale. + + :param user: L'utente da controllare. + :returns: `True` se l'utente deve poter modificare l'oggetto, altrimenti `False`. + + .. method:: can_admin(self, user: django.contrib.auth.models.User) -> bool + :abstractmethod: + + Controlla se un utente può amministrare l'oggetto attuale. + + :param user: L'utente da controllare. + :returns: `True` se l'utente deve poter amministrare l'oggetto, altrimenti `False`. + + .. classmethod:: get_fields(cls) -> set[str] + + :returns: il `set` di nomi di campi che devono essere mostrati quando viene richiesto l'oggetto attraverso l'API. + + .. classmethod:: get_editable_fields(cls) -> set[str] + + :returns: il `set` di nomi di campi di cui deve essere permessa la modifica se l'utente può modificare (`.can_edit`) l'oggetto. + + .. classmethod:: get_administrable_fields(cls) -> set[str] + + :returns: il `set` di nomi di campi di cui deve essere permessa la modifica se l'utente può amministrare (`.can_admin`) l'oggetto. + + .. classmethod:: get_creation_fields(cls) -> set[str] + + :returns: il `set` di nomi di campi che possono essere specificati dall'utente al momento della creazione dell'oggetto. + + +Modello di autorizzazione astratto +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Viene definito un nuovo modello astratto, basato su `SophonModel`, che permette di determinare i permessi dell'utente in base alla sua appartenenza al gruppo a cui è collegato l'oggetto implementatore. + +.. class:: SophonGroupModel(SophonModel) + + .. method:: get_group(self) -> ResearchGroup + :abstractmethod: + + :returns: Il gruppo a cui appartiene l'oggetto. + + .. classmethod:: get_access_to_edit(cls) -> sophon.core.enums.SophonGroupAccess + + :returns: Il livello di autorità all'interno del gruppo necessario per modificare l'oggetto. + + .. classmethod:: get_access_to_admin(cls) -> sophon.core.enums.SophonGroupAccess + + :returns: Il livello di autorità all'interno del gruppo necessario per amministrare l'oggetto. + + .. method:: get_access_serializer(self, user: User) -> typing.Type[rest_framework.serializers.ModelSerializer] + + :returns: Restituisce il `rest_framework.serializers.ModelSerializer` adeguato al livello di autorità dell'utente. + + +.. class:: sophon.core.enums.SophonGroupAccess(enum.IntEnum) + + Enumerazione che stabilisce il livello di autorità che un utente può avere all'interno di un gruppo. + + .. attribute:: NONE = 0 + + Utente :ref:`ospite`. + + .. attribute:: REGISTERED = 10 + + :ref:`Utente` registrato. + + .. attribute:: MEMBER = 50 + + Membro del :ref:`gruppo di ricerca`. + + .. attribute:: OWNER = 100 + + Creatore del :ref:`gruppo di ricerca`. + + .. attribute:: SUPERUSER = 200 + + :ref:`Superutente` con privilegi universali. + + +Modello dei dettagli dell'istanza +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Viene creato il modello che rappresenta i dettagli dell':ref:`istanza` Sophon. + +.. class:: SophonInstanceDetails(SophonModel) + + .. attribute:: id: IntegerField [1] + + Impostando ``1`` come unica scelta per il campo della chiave primaria ``id``, si crea un modello "singleton", ovvero un modello di cui può esistere un'istanza sola in tutto il database. + + L'istanza unica viene creata dalla migrazione ``0004_sophoninstancedetails.py``. + + .. attribute:: name: CharField + .. attribute:: description: TextField + .. attribute:: theme: CharField ["sophon", "paper", "royalblue", "hacker", "amber"] + + .. method:: version: str + :property: + + :returns: La versione installata del pacchetto `sophon`. + + .. seealso:: + + :ref:`Sophon instance details` nella guida per l'amministratore. + + +Modello del gruppo di ricerca +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Viene creato il modello che rappresenta un :ref:`gruppo di ricerca`. + +.. class:: ResearchGroup(SophonGroupModel) + + .. attribute:: slug: SlugField + .. attribute:: name: CharField + .. attribute:: description: TextField + .. attribute:: members: ManyToManyField → django.contrib.auth.models.User + .. attribute:: owner: ForeignKey → django.contrib.auth.models.User + .. attribute:: access: CharField ["MANUAL", "OPEN"] + + +Estensione ai permessi di Django +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. module:: sophon.core.permissions + +I permessi di `rest_framework` vengono estesi con due nuove classi che utilizzano il :ref:`modello di autorizzazione` precedentemente definito. + +.. class:: Edit(rest_framework.permissions.BasePermission) + + Consente l'interazione solo agli utenti che possono modificare (`.can_edit`) l'oggetto. + +.. class:: Admin(rest_framework.permissions.BasePermission) + + Consente l'interazione solo agli utenti che possono amministrare (`.can_admin`) l'oggetto. + + +Viewset astratti +^^^^^^^^^^^^^^^^ +.. module:: sophon.core.views + +Vengono definiti tre viewset in grado di utilizzare i metodi aggiunti dalle classi astratte `.models.SophonModel` e `.models.SophonGroupModel`. + +.. class:: ReadSophonViewSet(rest_framework.viewsets.ReadOnlyModelViewSet, metaclass=abc.ABCMeta) + + Classe **astratta** che estende la classe base `rest_framework.viewsets.ReadOnlyModelViewSet` con metodi di utilità mancanti nell'implementazione originale, allacciandola inoltre a `.models.SophonGroupModel`. + + .. method:: get_queryset(self) -> QuerySet + :abstractmethod: + + Imposta come astratto (e quindi obbligatorio) il metodo `rest_framework.viewsets.ReadOnlyModelViewSet.get_queryset`. + + .. method:: permission_classes(self) + :property: + + Sovrascrive il campo di classe `rest_framework.viewsets.ReadOnlyModelViewSet.permission_classes` con una funzione, permettendone la selezione dei permessi richiesti al momento di ricezione di una richiesta HTTP (invece che al momento di definizione della classe). + + Delega la selezione delle classi a `.get_permission_classes`. + + .. method:: get_permission_classes(self) -> typing.Collection[typing.Type[permissions.BasePermission]] + + Funzione che permette la selezione dei permessi necessari per effetuare una determinata richiesta al momento di ricezione di quest'ultima. + + Utile per le classi che erediteranno da questa. + + .. method:: get_serializer_class(self) -> typing.Type[Serializer] + + Funzione che permette la selezione del `rest_framework.serializers.Serializer` da utilizzare per una determinata richiesta al momento di ricezione di quest'ultima. + + Utilizza: + + - il serializzatore **in sola lettura** per elencare gli oggetti (azione ``list``); + - il serializzatore **di creazione** per creare nuovi oggetti (azione ``create``) e per generare i metadati del viewset (azione ``metadata``); + - il serializzatore ottenuto da `.models.SophonGroupModel.get_access_serializer` per la visualizzazione dettagliata (azione ``retrieve``), la modifica (azioni ``update`` e ``partial_update``) e l'eliminazione (azione ``destroy``) di un singolo oggetto; + - il serializzatore ottenuto da `.get_custom_serializer_classes` per le azioni personalizzate. + + .. seealso:: + + `.models.SophonGroupModel` + + .. method:: get_custom_serializer_classes(self) -> t.Type[Serializer] + + Permette alle classi che ereditano da questa di selezionare quale `rest_framework.serializers.Serializer` utilizzare per le azioni personalizzate. + +.. class:: WriteSophonViewSet(rest_framework.viewsets.ModelViewSet, ReadSophonViewSet, metaclass=abc.ABCMeta) + + Classe **astratta** che estende la classe base `ReadSophonViewSet` aggiungendoci i metodi di `rest_framework.viewsets.ModelViewSet` che effettuano modifiche sugli oggetti. + + Depreca i metodi ``perform_*`` di `rest_framework`, introducendone versioni migliorate con una signature diversa dal nome di ``hook_*``. + + .. method:: perform_create(self, serializer) + + .. deprecated:: 0.1 + + .. method:: perform_update(self, serializer) + + .. deprecated:: 0.1 + + .. method:: perform_destroy(self, serializer) + + .. deprecated:: 0.1 + + .. method:: hook_create(self, serializer) -> dict[str, typing.Any] + + Funzione chiamata durante l'esecuzione dell'azione di creazione oggetto ``create``. + + :param serializer: Il `~rest_framework.serializers.Serializer` già "riempito" contenente i dati dell'oggetto che sta per essere creato. + :raises .HTTPException: È possibile interrompere la creazione dell'oggetto con uno specifico codice errore sollevando una `.HTTPException` all'interno della funzione. + :returns: Un `dict` da unire a quello del `~rest_framework.serializers.Serializer` per formare l'oggetto da creare. + + .. method:: hook_update(self, serializer) -> dict[str, t.Any] + + Funzione chiamata durante l'esecuzione delle azioni di modifica oggetto ``update`` e ``partial_update``. + + :param serializer: Il `~rest_framework.serializers.Serializer` già "riempito" contenente i dati dell'oggetto che sta per essere modificato. + :raises .HTTPException: È possibile interrompere la creazione dell'oggetto con uno specifico codice errore sollevando una `.HTTPException` all'interno della funzione. + :returns: Un `dict` da unire a quello del `~rest_framework.serializers.Serializer` per formare l'oggetto da modificare. + + .. method:: hook_destroy(self, serializer) -> dict[str, typing.Any] + + Funzione chiamata durante l'esecuzione dell'azione di eliminazione oggetto ``destroy``. + + :raises .HTTPException: È possibile interrompere la creazione dell'oggetto con uno specifico codice errore sollevando una `.HTTPException` all'interno della funzione. + +.. exception:: sophon.core.errors.HTTPException + + Tipo di eccezione che è possibile sollevare nei metodi ``hook_*`` di `.WriteSophonViewSet` per interrompere l'azione in corso senza applicare le modifiche. + + .. attribute:: status: int + + Permette di specificare il codice errore con cui rispondere alla richiesta interrotta. + + +.. class:: SophonGroupViewSet(WriteSophonViewSet, metaclass=abc.ABCMeta) + + Classe **astratta** che estende la classe base `.WriteSophonViewSet` estendendo gli ``hook_*`` con verifiche dei permessi dell'utente che tenta di effettuare l'azione. + + .. method:: get_group_from_serializer(self, serializer) -> models.ResearchGroup + :abstractmethod: + + Metodo necessario a trovare il gruppo a cui apparterrà un oggetto prima che il suo serializzatore venga elaborato. + + :param serializer: Il `~rest_framework.serializers.Serializer` già "riempito" contenente i dati dell'oggetto. + + +Viewset concreti +^^^^^^^^^^^^^^^^ + +Vengono poi definiti tre viewset e una view che permettono interazioni tra l'utente e i modelli definiti nell'app. + +.. class:: UsersByIdViewSet(ReadSophonViewSet) + + Viewset in sola lettura che permette di recuperare gli utenti dell'istanza partendo dal loro ``id``. + + Accessibile all'URL :samp:`/api/core/users/by-id/{ID}/`. + +.. class:: UsersByUsernameViewSet(ReadSophonViewSet) + + Viewset in sola lettura che permette di recuperare gli utenti dell'istanza partendo dal loro ``username``. + + Accessibile all'URL :samp:`/api/core/users/by-username/{USERNAME}/`. + +.. class:: ResearchGroupViewSet(WriteSophonViewSet) + + Viewset in lettura e scrittura che permette di interagire con i gruppi di ricerca. + + Accessibile all'URL :samp:`/api/core/groups/{GROUP_SLUG}/`. + + .. method:: join(self, request: Request, pk: int) -> Response + + Azione personalizzata che permette ad un utente di unirsi ad un gruppo aperto. + + Utilizza `.models.SophonGroupModel.get_access_serializer`. + + .. method:: leave(self, request: Request, pk: int) -> Response + + Azione personalizzata che permette ad un utente di abbandonare un gruppo di cui non è proprietario. + + Utilizza `.models.SophonGroupModel.get_access_serializer`. + +.. class:: SophonInstanceDetailsView(APIView) + + View che restituisce il valore attuale dell'unico oggetto `.models.SophonInstanceDetails`. + + Accessibile tramite richieste ``GET`` all'URL :samp:`/api/core/instance/`. + + +Pagina di amministrazione +^^^^^^^^^^^^^^^^^^^^^^^^^ +.. module:: sophon.core.admin + +Vengono infine registrati nella pagina di amministrazione i modelli concreti definiti in questa app, effettuando alcune personalizzazioni elencate in seguito. + +.. class:: ResearchGroupAdmin(SophonAdmin) + + Per i gruppi di ricerca, viene specificato un ordinamento, permesso il filtraggio e selezionati i campi più importanti da visualizzare nella lista. + +.. class:: SophonInstanceDetails(SophonAdmin) + + Per i dettagli dell'istanza, vengono disattivate tutte le azioni, impedendo la creazione o eliminazione del singleton. + + diff --git a/report/source/3_dev/2_structure/1_backend/4_projects.rst b/report/source/3_dev/2_structure/1_backend/4_projects.rst new file mode 100644 index 0000000..54be5db --- /dev/null +++ b/report/source/3_dev/2_structure/1_backend/4_projects.rst @@ -0,0 +1,62 @@ +L'app sophon.projects +----------------------- +.. default-domain:: py +.. default-role:: obj +.. module:: sophon.projects + +L'app `sophon.projects` è un app secondaria che dipende da `sophon.core` che introduce in Sophon il concetto di :ref:`progetto di ricerca`. + +.. caution:: + + Anche se l'app `sophon.projects` è opzionale (il progetto può funzionare senza di essa), si sconsiglia di disattivarla, in quanto il :ref:`modulo frontend` si aspetta che l'app sia attiva e solleverà un errore nel caso che i viewset forniti da questa app non siano disponibile. + + +Modello del progetto di ricerca +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. module:: sophon.projects.models + +Viene introdotto un modello concreto che rappresenta un :ref:`progetto di ricerca`. + +.. class:: ResearchProject(SophonGroupModel) + + .. attribute:: slug: SlugField + .. attribute:: group: ForeignKey → sophon.core.models.ResearchGroup + .. attribute:: name: CharField + .. attribute:: description: TextField + .. attribute:: visibility: CharField ["PUBLIC", "INTERNAL", "PRIVATE"] + + +Viewset del gruppo di ricerca +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. module:: sophon.projects.views + +Da una base comune, vengono creati due viewset per interagire con i progetti di ricerca. + +.. class:: ResearchProjectViewSet(SophonGroupViewSet, metaclass=abc.ABCMeta) + + Classe **astratta** che effettua l'override di `~sophon.core.views.SophonGroupView.get_group_from_serializer` per entrambi i viewset che seguono. + +.. class:: ResearchProjectsBySlugViewSet(ResearchProjectViewSet) + + Viewset in lettura e scrittura che permette di interagire con tutti i progetti di ricerca a cui l'utente loggato ha accesso. + + Accessibile all'URL :samp:`/api/projects/by-slug/{PROJECT_SLUG}/`. + +.. class:: ResearchProjectsByGroupViewSet(ResearchProjectViewSet) + + Viewset in lettura e scrittura che permette di interagire con i progetti di ricerca a cui l'utente loggato ha accesso, filtrati per il gruppo a cui appartengono. + + Il filtraggio viene effettuato limitando il queryset. + + Accessibile all'URL :samp:`/api/projects/by-group/{GROUP_SLUG}/{PROJECT_SLUG}/`. + + +Amministrazione del gruppo di ricerca +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. module:: sophon.projects.admin + +Il modello `.models.ResearchProject` viene registrato nella pagina di amministrazione attraverso la seguente classe: + +.. class:: ResearchProjectAdmin(sophon.core.admin.SophonAdmin) + + Classe per la pagina di amministrazione che specifica un ordinamento, permette il filtraggio per gruppo di appartenenza e visibilità, e specifica i campi da visualizzare nell'elenco dei progetti. diff --git a/report/source/3_dev/2_structure/1_backend/5_notebooks.rst b/report/source/3_dev/2_structure/1_backend/5_notebooks.rst new file mode 100644 index 0000000..7794181 --- /dev/null +++ b/report/source/3_dev/2_structure/1_backend/5_notebooks.rst @@ -0,0 +1,241 @@ +L'app sophon.notebooks +---------------------- +.. default-domain:: py +.. default-role:: obj +.. module:: sophon.notebooks + + +L'app `sophon.notebooks` è un app secondaria che dipende da `sophon.projects` che introduce in Sophon il concetto di :ref:`notebook`. + +.. caution:: + + Anche se l'app `sophon.notebooks` è opzionale (il progetto può funzionare senza di essa), si sconsiglia di disattivarla, in quanto il :ref:`modulo frontend` si aspetta che l'app sia attiva e solleverà un errore nel caso che i viewset forniti da questa app non siano disponibile. + + +Funzionamento di un notebook +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Internamente, un notebook non è altro che un container Docker accessibile ad un determinato indirizzo il cui stato è sincronizzato con un oggetto del database del :ref:`modulo backend`. + + +Modalità sviluppo +""""""""""""""""" + +Per facilitare lo sviluppo di Sophon, sono previste due modalità di operazione di quest'ultimo: + +- nella prima, la **modalità sviluppo**, il :ref:`modulo proxy` non è in esecuzione, ed è possibile collegarsi direttamente ai container attraverso collegamenti a ``localhost``; + +- nella seconda, la **modalità produzione**, il :ref:`modulo proxy` è in esecuzione all'interno di un container Docker, e si collega agli altri container attraverso i rispettivi network Docker agli indirizzi comunicatogli dal :ref:`modulo backend`. + + .. image:: notebooks_diagram.png + + +Gestione della rubrica del proxy +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. module:: sophon.notebooks.apache + +Viene creata una classe per la gestione della rubrica del proxy, utilizzando il modulo `dbm.gnu`, supportato da HTTPd. + +La rubrica mappa gli URL pubblici dei notebook a URL privati relativi al :ref:`modulo proxy`, in modo da effettuare reverse proxying **dinamico**. + +.. class:: ApacheDB + + Classe che permette il recupero, la creazione, la modifica e l'eliminazioni di chiavi di un database `dbm.gnu` come se quest'ultimo fosse un `dict` con supporto a chiavi e valori `str` e `bytes`. + + .. staticmethod:: convert_to_bytes(item: typing.Union[str, bytes]) -> bytes + + Tutte le `str` passate a questa classe vengono convertite in `bytes` attraverso questa funzione, che effettua un encoding in ASCII e solleva un errore se quest'ultimo fallisce. + + +Assegnazione porta effimera +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In *modalità sviluppo*, è necessario trovare una porta libera a cui rendere accessibile i container Docker dei notebook. + +.. function:: get_ephemeral_port() -> int + + Questa funzione apre e chiude immediatamente un `socket.socket` all'indirizzo ``localhost:0`` in modo da ricevere dal sistema operativo un numero di porta sicuramente libero. + + +Connessione al daemon Docker +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. module:: sophon.notebooks.docker + +Per facilitare l'utilizzo del daemon Docker per la gestione dei container dei notebook, viene utilizzato il modulo `docker`. + +.. function:: get_docker_client() -> docker.DockerClient + + Funzione che crea un client Docker con le variabili di ambiente del modulo. + +.. data:: client: docker.DockerClient = lazy_object_proxy.Proxy(get_docker_client) + + Viene creato un client Docker globale con inizializzazione lazy al fine di non tentare connessioni (lente!) al daemon quando non sono necessarie. + + +Controllo dello stato di salute +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Il modulo `docker` viene esteso implementando supporto per l'istruzione ``HEALTHCHECK`` dei ``Dockerfile``. + +.. class:: HealthState(enum.IntEnum) + + Enumerazione che elenca gli stati possibili in cui può essere la salute di un container. + + .. attribute:: UNDEFINED = -2 + + Il ``Dockerfile`` non ha un ``HEALTHCHECK`` definito. + + .. attribute:: STARTING = -1 + + Il container Docker non mai completato con successo un ``HEALTHCHECK``. + + .. attribute:: HEALTHY = 0 + + Il container Docker ha completato con successo l'ultimo ``HEALTHCHECK`` e quindi sta funzionando correttamente. + + .. attribute:: UNHEALTHY = 1 + + Il container Docker ha fallito l'ultimo ``HEALTHCHECK``. + + +.. function:: get_health(container: docker.models.containers.Container) -> HealthState + + Funzione che utilizza l'API a basso livello del client Docker per recuperare l'`HealthState` dei container. + +.. function:: sleep_until_container_has_started(container: docker.models.containers.Container) -> HealthState + + Funzione bloccante che restituisce solo quando lo stato del container specificato non è `HealthState.STARTING`. + + +Generazione di token sicuri +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Si è scelto di rendere completamente trasparente all'utente il meccanismo di autenticazione a JupyterLab. + +Pertanto, si è verificata la necessità di generare token crittograficamente sicuri da richiedere per l'accesso a JupyterLab. + +.. function:: generate_secure_token() -> str + + Funzione che utilizza `secrets.token_urlsafe` per generare un token valido e crittograficamente sicuro. + + +Modello dei notebook +^^^^^^^^^^^^^^^^^^^^ +.. module:: sophon.notebooks.models + +Viene definito il modello rappresentante un :ref:`notebook`. + +.. class:: Notebook(SophonGroupModel) + + .. attribute:: slug: SlugField + + Lo slug dei notebook prevede ulteriori restrizioni oltre a quelle previste dallo `django.db.models.SlugField`: + + - non può essere uno dei seguenti valori: ``api``, ``static``, ``proxy``, ``backend``, ``frontend``, ``src``; + - non può iniziare o finire con un trattino ``-``. + + .. attribute:: project: ForeignKey → sophon.projects.models.ResearchProject + .. attribute:: name: CharField + .. attribute:: locked_by: ForeignKey → django.contrib.auth.models.User + + .. attribute:: container_image: CharField ["ghcr.io/steffo99/sophon-jupyter"] + + Campo che specifica l'immagine che il client Docker dovrà avviare per questo notebook. + + Al momento ne è configurata una sola per semplificare l'esperienza utente, ma altre possono essere specificate per permettere agli utenti più scelta. + + .. note:: + + Al momento, le immagini specificate devono esporre un server web sulla porta ``8888``, e supportare il protocollo di connessione di Jupyter, ovvero :samp:`{PROTOCOLLO}://immagine:8888/lab?token={TOKEN}` e :samp:`{PROTOCOLLO}://immagine:8888/tree?token={TOKEN}`. + + .. attribute:: jupyter_token: CharField + + Il token segreto che verrà passato attraverso le variabili di ambiente al container Docker dell'oggetto per permettere solo agli utenti autorizzati di accedere a quest'ultimo. + + .. attribute:: container_id: CharField + + L'id assegnato dal daemon Docker al container di questo oggetto. + + Se il notebook non è avviato, questo attributo varrà `None`. + + .. attribute:: port: IntegerField + + La porta assegnata al container Docker dell'oggetto nel caso in cui Sophon sia avviato in "modalità sviluppo", ovvero con il :ref:`modulo proxy` in esecuzione sul sistema host. + + .. attribute:: internal_url: CharField + + L'URL a cui è accessibile il container Docker dell'oggetto nel caso in cui Sophon non sia avviato in "modalità sviluppo", ovvero con il :ref:`modulo proxy` in esecuzione all'interno di un container. + + .. method:: log(self) -> logging.Logger + :property: + + Viene creato un `logging.Logger` per ogni oggetto della classe, in modo da facilitare il debug relativo ad uno specifico notebook. + + Il nome del logger ha la forma :samp:`sophon.notebooks.models.Notebook.{NOTEBOOK_SLUG}`. + + .. method:: enable_proxying(self) -> None + + Aggiunge l'indirizzo del notebook alla rubrica del proxy. + + .. method:: disable_proxying(self) -> None + + Rimuove l'indirizzo del notebook dalla rubrica del proxy. + + .. method:: sync_container(self) -> t.Optional[docker.models.containers.Container] + + Sincronizza lo stato dell'oggetto nel database con lo stato del container Docker nel sistema. + + .. method:: create_container(self) -> docker.models.containers.Container + + Crea e configura un container Docker per l'oggetto, con l'immagine specificata in `.container_image`. + + .. method:: start(self) -> None + + Tenta di creare e avviare un container Docker per l'oggetto, bloccando fino a quando esso non sarà avviato con `~.docker.sleep_until_container_has_started`. + + .. method:: stop(self) -> None + + Arresta il container Docker dell'oggetto. + + +Viewset dei notebook +^^^^^^^^^^^^^^^^^^^^ +.. module:: sophon.notebooks.views + +Come per il modulo `sophon.projects`, vengono creati due viewset per interagire con i progetti di ricerca, basati entrambi su un viewset astratto che ne definisce le proprietà comuni. + +.. class:: NotebooksViewSet(SophonGroupViewSet, metaclass=abc.ABCMeta) + + Classe **astratta** che effettua l'override di `~sophon.core.views.SophonGroupView.get_group_from_serializer` e definisce cinque azioni personalizzate per l'interazione con il notebook. + + .. method:: sync(self, request: Request, **kwargs) -> Response + + Azione personalizzata che sincronizza lo stato dell'oggetto dell'API con quello del daemon Docker. + + .. method:: start(self, request: Request, **kwargs) -> Response + + Azione personalizzata che avvia il notebook con `.models.Notebook.start`. + + .. method:: stop(self, request: Request, **kwargs) -> Response + + Azione personalizzata che arresta il notebook con `.models.Notebook.stop`. + + .. method:: lock(self, request: Request, **kwargs) -> Response + + Azione personalizzata che blocca il notebook impostando il campo `.models.Notebook.locked_by` all'utente che ha effettuato la richiesta. + + .. method:: unlock(self, request: Request, **kwargs) -> Response + + Azione personalizzata che sblocca il notebook impostando il campo `.models.Notebook.locked_by` a `None`. + +.. class:: NotebooksBySlugViewSet(NotebooksViewSet) + + Viewset in lettura e scrittura che permette di interagire con tutti i notebook a cui l'utente loggato ha accesso. + + Accessibile all'URL :samp:`/api/notebooks/by-slug/{NOTEBOOK_SLUG}/`. + +.. class:: NotebooksByProjectViewSet(NotebooksViewSet) + + Viewset in lettura e scrittura che permette di interagire con i notebook a cui l'utente loggato ha accesso, filtrati per il progetto di appartenenza. + + Accessibile all'URL :samp:`/api/notebooks/by-project/{PROJECT_SLUG}/{NOTEBOOK_SLUG/`. diff --git a/report/source/3_dev/2_structure/1_backend/6_ci.rst b/report/source/3_dev/2_structure/1_backend/6_ci.rst new file mode 100644 index 0000000..decbd15 --- /dev/null +++ b/report/source/3_dev/2_structure/1_backend/6_ci.rst @@ -0,0 +1,6 @@ +Continuous Integration +---------------------- + +Il codice sorgente del modulo viene automaticamente controllato attraverso GitHub Actions da **CodeQL** e **Dependabot** ad ogni modifica, segnalando gli eventuali errori o dipendenze non aggiornate nel pannello *Security* del repository. + +.. image:: ci_example.png diff --git a/report/source/3_dev/2_structure/1_backend/7_cd.rst b/report/source/3_dev/2_structure/1_backend/7_cd.rst new file mode 100644 index 0000000..15875b9 --- /dev/null +++ b/report/source/3_dev/2_structure/1_backend/7_cd.rst @@ -0,0 +1,12 @@ +Continuous Deployment +--------------------- + +L'immagine del modulo viene automaticamente ricompilata da GitHub Actions e pubblicata su GitHub Containers ogni volta che un file all'interno della cartella del modulo viene modificato. + +Questo workflow è definito all'interno del file ``.github/workflows/build-docker-backend.yml``. + +.. image:: cd_example.png + +.. seealso:: + + `La pagina del container `_ su GitHub Containers. diff --git a/report/source/3_dev/2_structure/1_backend/cd_example.png b/report/source/3_dev/2_structure/1_backend/cd_example.png new file mode 100644 index 0000000..4a0d530 --- /dev/null +++ b/report/source/3_dev/2_structure/1_backend/cd_example.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ddb75f9bab60af6d5cddb6a4d299ce26a5380098156a674084bd8f4bb437ea63 +size 73566 diff --git a/report/source/3_dev/2_structure/1_backend/ci_example.png b/report/source/3_dev/2_structure/1_backend/ci_example.png new file mode 100644 index 0000000..6df3401 --- /dev/null +++ b/report/source/3_dev/2_structure/1_backend/ci_example.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ba93c42828ac0ad037f51f8b179f19b735a2c8ef7c0a021db9f99ccec75290a +size 77445 diff --git a/report/source/3_dev/2_structure/1_backend/index.rst b/report/source/3_dev/2_structure/1_backend/index.rst new file mode 100644 index 0000000..41e91c4 --- /dev/null +++ b/report/source/3_dev/2_structure/1_backend/index.rst @@ -0,0 +1,28 @@ +Modulo backend +============== +.. default-domain:: py +.. default-role:: obj +.. py:currentmodule:: sophon + +Il *modulo backend* consiste in un server web che espone un'API e un sito web per l'amministrazione. + +È collocato all'interno del repository in ``/backend``. + +È formato dal package Python `sophon`, che contiene al suo interno un progetto Django, che a sua volta contiene le tre app Django `sophon.core`, `sophon.projects` e `sophon.notebooks`. + +.. note:: + + A causa della dipendenza di Django da variabili globali, è stato impossibile utilizzare lo strumento di documentazione automatica `sphinx.ext.autodoc`. + + Pertanto, si è deciso di documentare soltanto le classi e metodi più rilevanti ai fini di questa documentazione. + +.. toctree:: + :maxdepth: 1 + + 1_techstack + 2_sophon + 3_core + 4_projects + 5_notebooks + 6_ci + 7_cd diff --git a/report/source/3_dev/2_structure/1_backend/notebooks_diagram.png b/report/source/3_dev/2_structure/1_backend/notebooks_diagram.png new file mode 100644 index 0000000..ab2179e --- /dev/null +++ b/report/source/3_dev/2_structure/1_backend/notebooks_diagram.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8be4a56a78897a83786260eb471475ff56e2f94f73002167d5a26b460f8b25ba +size 134333 diff --git a/report/source/3_dev/2_structure/2_frontend/1_techstack.rst b/report/source/3_dev/2_structure/2_frontend/1_techstack.rst new file mode 100644 index 0000000..01ae551 --- /dev/null +++ b/report/source/3_dev/2_structure/2_frontend/1_techstack.rst @@ -0,0 +1,17 @@ +Librerie e tecnologie utilizzate +-------------------------------- + +.. note:: + + Sono elencate solo le principali librerie utilizzate; dipendenze e librerie minori non sono specificate, ma sono visibili all'interno del file ``yarn.lock``. + +- I linguaggi di programmazione `JavaScript `_ e `TypeScript `_ + - Il gestore di dipendenze `Yarn `_ + - La libreria grafica `Bluelib `_ (sviluppata come progetto personale nell'estate 2021) + - Il framework per interfacce grafiche `React `_ + - Il router `Reach Router `_ + - L'integrazione con React di Bluelib `bluelib-react `_ (sviluppata durante il tirocinio) + - Il componente React `react-markdown `_ + - Il framework per testing `Jest `_ + - Un fork personalizzato del client XHR `axios `_ +- Il webserver statico `serve `_ diff --git a/report/source/3_dev/2_structure/2_frontend/2_tree.rst b/report/source/3_dev/2_structure/2_frontend/2_tree.rst new file mode 100644 index 0000000..4c9e3e6 --- /dev/null +++ b/report/source/3_dev/2_structure/2_frontend/2_tree.rst @@ -0,0 +1,23 @@ +Struttura delle directory +------------------------- +.. default-domain:: js + +Le directory di :mod:`@steffo45/sophon-frontend` sono strutturate nella seguente maniera: + +src/components + Contiene i componenti React sia con le classi sia funzionali. + +src/contexts + Contiene i contesti React creati con :func:`React.createContext`. + +src/hooks + Contiene gli hook React personalizzati utilizzati nei componenti funzionali. + +src/types + Contiene estensioni ai tipi base TypeScript, come ad esempio i tipi restituiti dalla web API del :ref:`modulo backend`. + +src/utils + Contiene varie funzioni di utility. + +public + Contiene i file statici da servire assieme all'app. diff --git a/report/source/3_dev/2_structure/2_frontend/3_resources.rst b/report/source/3_dev/2_structure/2_frontend/3_resources.rst new file mode 100644 index 0000000..4710dba --- /dev/null +++ b/report/source/3_dev/2_structure/2_frontend/3_resources.rst @@ -0,0 +1,113 @@ +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`. diff --git a/report/source/3_dev/2_structure/2_frontend/4_contexts.rst b/report/source/3_dev/2_structure/2_frontend/4_contexts.rst new file mode 100644 index 0000000..0d8850a --- /dev/null +++ b/report/source/3_dev/2_structure/2_frontend/4_contexts.rst @@ -0,0 +1,162 @@ +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 + + ("/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 + + + + unselected: + + selected: + + + unselected: + + selected: + + + unselected: + + selected: + + + unselected: + + selected: + + + unselected: + + selected: + + + +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. diff --git a/report/source/3_dev/2_structure/2_frontend/5_ci.rst b/report/source/3_dev/2_structure/2_frontend/5_ci.rst new file mode 100644 index 0000000..decbd15 --- /dev/null +++ b/report/source/3_dev/2_structure/2_frontend/5_ci.rst @@ -0,0 +1,6 @@ +Continuous Integration +---------------------- + +Il codice sorgente del modulo viene automaticamente controllato attraverso GitHub Actions da **CodeQL** e **Dependabot** ad ogni modifica, segnalando gli eventuali errori o dipendenze non aggiornate nel pannello *Security* del repository. + +.. image:: ci_example.png diff --git a/report/source/3_dev/2_structure/2_frontend/6_cd.rst b/report/source/3_dev/2_structure/2_frontend/6_cd.rst new file mode 100644 index 0000000..54e3704 --- /dev/null +++ b/report/source/3_dev/2_structure/2_frontend/6_cd.rst @@ -0,0 +1,12 @@ +Continuous Deployment +--------------------- + +L'immagine del modulo viene automaticamente ricompilata da GitHub Actions e pubblicata su GitHub Containers ogni volta che un file all'interno della cartella del modulo viene modificato. + +Questo workflow è definito all'interno del file ``.github/workflows/build-docker-frontend.yml``. + +.. image:: cd_example.png + +.. seealso:: + + `La pagina del container `_ su GitHub Containers. diff --git a/report/source/3_dev/2_structure/2_frontend/cd_example.png b/report/source/3_dev/2_structure/2_frontend/cd_example.png new file mode 100644 index 0000000..a303cb0 --- /dev/null +++ b/report/source/3_dev/2_structure/2_frontend/cd_example.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a4aa4bde19efa94508d62d97ff862a876d311e934f2b92002c9e033ce187a70 +size 31703 diff --git a/report/source/3_dev/2_structure/2_frontend/ci_example.png b/report/source/3_dev/2_structure/2_frontend/ci_example.png new file mode 100644 index 0000000..a018a25 --- /dev/null +++ b/report/source/3_dev/2_structure/2_frontend/ci_example.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e9add7c6f78640adfb9093cf51ec2119c1fe4fb7467e87018f7e2652b7100e3 +size 69090 diff --git a/report/source/3_dev/2_structure/2_frontend/index.rst b/report/source/3_dev/2_structure/2_frontend/index.rst new file mode 100644 index 0000000..75f6957 --- /dev/null +++ b/report/source/3_dev/2_structure/2_frontend/index.rst @@ -0,0 +1,22 @@ +Modulo frontend +=============== +.. default-domain:: js + +Il *modulo frontend* consiste in una interfaccia web che consente agli utenti di interagire con il :ref:`modulo backend` e di accedere al :ref:`modulo Jupyter`. + +Si è cercato di renderla più user-friendly possibile, cercando di comunicare più informazioni possibili all'utente attraverso colori e icone, rendendo possibile apprendere ad utilizzare l'interfaccia intuitivamente. + +È collocato all'interno del repository in ``/frontend``. + +Il modulo è formato dal package JavaScript :mod:`@steffo45/sophon-frontend`, che contiene tutti i componenti React che assemblati insieme formano l'intera interfaccia web. + +.. toctree:: + :maxdepth: 1 + + 1_techstack + 2_tree + 3_resources + 4_contexts + 5_ci + 6_cd + diff --git a/report/source/3_dev/2_structure/3_proxy/index.rst b/report/source/3_dev/2_structure/3_proxy/index.rst new file mode 100644 index 0000000..0a15e51 --- /dev/null +++ b/report/source/3_dev/2_structure/3_proxy/index.rst @@ -0,0 +1,111 @@ +Modulo proxy +============ + +Il *modulo proxy* consiste in un webserver che riceve tutte le richieste HTTP dirette ad uno degli altri moduli e le smista in base a regole statiche e dinamiche. + +È collocato all'interno del repository in ``/proxy``. + + +Tecnologie utilizzate +--------------------- + +- Il server web `Apache HTTPd`_ + - Il modulo `rewrite`_ + - Il modulo `proxy`_ + - Il modulo `proxy_http`_ + - Il modulo `proxy_wstunnel`_ + +.. _Apache HTTPd: https://httpd.apache.org/ +.. _rewrite: https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html +.. _proxy: https://httpd.apache.org/docs/2.4/mod/mod_proxy.html +.. _proxy_http: https://httpd.apache.org/docs/2.4/mod/mod_proxy_http.html +.. _proxy_wstunnel: https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html + + +Funzionamento del modulo +------------------------ + +Il modulo proxy è composto da un file di configurazione di `Apache HTTPd`_ e di un ``Dockerfile`` che lo copia all'interno dell'immagine Docker ufficiale ``httpd:2.4``. + +Il file di configurazione abilita i moduli `rewrite`_, `proxy`_, `proxy_wstunnel`_ e `proxy_http`_, impostando quest'ultimo per inoltrare l'header `Host `_ alle pagine verso cui viene effettuato reverse proxying. + +Inoltre, nel file di configurazione viene abilitato il ``RewriteEngine``, che viene utilizzato per effettuare reverse proxying secondo le seguenti regole: + +#. Tutte le richieste verso ``static.`` prefisso ad :ref:`\`\`APACHE_PROXY_BASE_DOMAIN\`\`` vengono processate direttamente dal webserver, utilizzando i file disponibili nella cartella ``/var/www/html/django-static`` che gli vengono forniti dal volume ``django-static`` del :ref:`modulo backend`. + + .. code-block:: apacheconf + + # If ENV:APACHE_PROXY_BASE_DOMAIN equals HTTP_HOST + RewriteCond "static.%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) \1$" [NC] + # Process the request yourself + RewriteRule ".?" - [L] + +#. Tutte le richieste verso :ref:`\`\`APACHE_PROXY_BASE_DOMAIN\`\`` senza nessun sottodominio vengono inoltrate al container Docker del :ref:`modulo frontend` utilizzando la risoluzione dei nomi di dominio di Docker Compose. + + .. code-block:: apacheconf + + # If ENV:APACHE_PROXY_BASE_DOMAIN equals HTTP_HOST + RewriteCond "%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) \1$" [NC] + # Capture ENV:SOPHON_FRONTEND_NAME for substitution in the rewriterule + RewriteCond "%{ENV:SOPHON_FRONTEND_NAME}" "^(.+)$" [NC] + # Forward to the frontend + RewriteRule "/(.*)" "http://%1/$1" [P,L] + +#. Tutte le richieste verso ``api.`` prefisso ad :ref:`\`\`APACHE_PROXY_BASE_DOMAIN\`\`` vengono inoltrate al container Docker del :ref:`modulo backend` utilizzando la risoluzione dei nomi di dominio di Docker Compose. + + .. code-block:: apacheconf + + # If api. prefixed to ENV:APACHE_PROXY_BASE_DOMAIN equals HTTP_HOST + RewriteCond "api.%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) \1$" [NC] + # Capture ENV:SOPHON_BACKEND_NAME for substitution in the rewriterule + RewriteCond "%{ENV:SOPHON_BACKEND_NAME}" "^(.+)$" [NC] + # Forward to the backend + RewriteRule "/(.*)" "http://%1/$1" [P,L] + +#. Carica in memoria la rubrica dei notebook generata dal :ref:`modulo backend` e disponibile in ``/run/sophon/proxy/proxy.dbm`` attraverso il volume ``proxy-data``, assegnandogli il nome di ``sophonproxy``. + + .. code-block:: apacheconf + + # Create a map between the proxy file generated by Sophon and Apache + RewriteMap "sophonproxy" "dbm=gdbm:/run/sophon/proxy/proxy.dbm" + +#. Effettua il proxying dei websocket verso i notebook mappati dalla rubrica ``sophonproxy``. + + .. code-block:: apacheconf + + # If this is any other subdomain of ENV:APACHE_PROXY_BASE_DOMAIN + RewriteCond ".%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) [^ ]+\1$" [NC] + # If this is a websocket connection + RewriteCond "%{HTTP:Connection}" "Upgrade" [NC] + RewriteCond "%{HTTP:Upgrade}" "websocket" [NC] + # Forward to the notebook + RewriteRule "/(.*)" "ws://${sophonproxy:%{HTTP_HOST}}/$1" [P,L] + +#. Effettua il proxying delle richieste "normali" verso i notebook mappati dalla rubrica ``sophonproxy``. + + .. code-block:: apacheconf + + # If this is any other subdomain of ENV:APACHE_PROXY_BASE_DOMAIN + RewriteCond ".%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) [^ ]+\1$" [NC] + # Forward to the notebook + RewriteRule "/(.*)" "http://${sophonproxy:%{HTTP_HOST}}/$1" [P,L] + +Tutte le regole usano il flag ``L`` di ``RewriteRule``, che porta il motore di rewriting a ignorare tutte le regole successive, come il ``return`` di una funzione di un linguaggio di programmazione imperativo. + +.. note:: + + I blocchi di codice all'interno di questa sezione sono stati inseriti manualmente e potrebbero non essere interamente aggiornati alla versione più recente del file. + + Si consiglia di consultare il file ``httpd.conf`` in caso si necessiti di informazioni aggiornate. + + +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-proxy.yml``. + +.. seealso:: + + `La pagina del container `_ su GitHub Containers. diff --git a/report/source/3_dev/2_structure/4_jupyter/index.rst b/report/source/3_dev/2_structure/4_jupyter/index.rst new file mode 100644 index 0000000..e13a356 --- /dev/null +++ b/report/source/3_dev/2_structure/4_jupyter/index.rst @@ -0,0 +1,87 @@ +Modulo Jupyter +============== + +Il *modulo Jupyter* consiste in un ambiente `Jupyter `_ e `JupyterLab `_ modificato per una migliore integrazione con Sophon, in particolare con il :ref:`modulo frontend` e il :ref:`modulo backend`. + +È collocato all'interno del repository in ``/jupyter``. + +Progetti utilizzati +------------------- + +- Le immagini Docker ufficiali di Jupyter `jupyter/docker-stacks `_ +- Il tema `JupyterLab Sophon `_ (realizzato durante il tirocinio) +- Il tool per il trasferimento dati `curl `_ + + +Funzionamento del modulo +------------------------ + +Il modulo è composto da un singolo ``Dockerfile`` che crea un immagine Docker in quattro fasi: + +#. **Base**: Parte dall'immagine base ``jupyter/scipy-notebook`` ed altera i label dell'immagine; + + .. code-block:: docker + + FROM jupyter/scipy-notebook AS base + # Set the maintainer label + LABEL maintainer="Stefano Pigozzi " + +#. **Env**: Configura le variabili di ambiente dell'immagine, attivando JupyterLab, configurando il riavvio automatico di Jupyter e permettendo all'utente non-privilegiato di acquisire i privilegi di root attraverso il comando ``sudo``; + + .. code-block:: docker + + FROM base AS env + # Set useful envvars for Sophon notebooks + ENV JUPYTER_ENABLE_LAB=yes + ENV RESTARTABLE=yes + ENV GRANT_SUDO=yes + +#. **Extensions**: Installa, abilita e configura le estensioni necessarie all'integrazione con Sophon (attualmente, soltanto il tema JupyterLab Sophon); + + .. code-block:: docker + + FROM env AS extensions + # As the default user... + USER ${NB_UID} + WORKDIR "${HOME}" + # Install the JupyterLab Sophon theme + RUN jupyter labextension install "jupyterlab_theme_sophon" + # Enable the JupyterLab Sophon theme + RUN jupyter labextension enable "jupyterlab_theme_sophon" + # Set the JupyterLab Sophon theme as default + RUN mkdir -p '.jupyter/lab/user-settings/@jupyterlab/apputils-extension/' + RUN echo '{"theme": "JupyterLab Sophon"}' > ".jupyter/lab/user-settings/@jupyterlab/apputils-extension/themes.jupyterlab-settings" + +#. **Healthcheck**: Installa ``curl``, e aggiunge all'immagine un controllo per verificarne lo stato di avvio, permettendo al :ref:`modulo backend` di comunicare una richiesta di avvio riuscita solo quando l'intera immagine è avviata + + .. code-block:: docker + + FROM extensions AS healthcheck + # As root... + USER root + # Install curl + RUN apt-get update + RUN apt-get install -y curl + # Use curl to check the health status + HEALTHCHECK --start-period=5s --timeout=5s --interval=10s CMD ["curl", "--output", "/dev/null", "http://localhost:8888"] + + # We probably should go back to the default user + USER ${NB_UID} + +.. note:: + + I blocchi di codice all'interno di questa sezione sono stati inseriti manualmente e potrebbero non essere interamente aggiornati alla versione più recente del file. + + Si consiglia di consultare il ``Dockerfile`` in caso si necessiti di informazioni aggiornate. + + +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-jupyter.yml``. + +.. seealso:: + + `La pagina del container `_ su GitHub Containers. diff --git a/report/source/3_dev/2_structure/index.rst b/report/source/3_dev/2_structure/index.rst new file mode 100644 index 0000000..a421997 --- /dev/null +++ b/report/source/3_dev/2_structure/index.rst @@ -0,0 +1,13 @@ +Struttura del progetto +********************** + +Sophon è composto da quattro moduli, *backend*, *frontend*, *proxy* e *jupyter*, che interagiscono tra loro per fornire agli utenti tutti i servizi necessari. + + +.. toctree:: + :maxdepth: 2 + + 1_backend/index + 2_frontend/index + 3_proxy/index + 4_jupyter/index diff --git a/report/source/3_dev/3_differences/index.rst b/report/source/3_dev/3_differences/index.rst new file mode 100644 index 0000000..1bcceb2 --- /dev/null +++ b/report/source/3_dev/3_differences/index.rst @@ -0,0 +1,27 @@ +Differenze da altri progetti simili +*********************************** + +Sophon a prima vista può sembrare simile ad altri progetti già esistenti, ma si differenzia in alcune particolarità del suo funzionamento. + + +Differenze da JupyterHub +======================== + +`JupyterHub`_ è un progetto con scopi molto simili a quelli di Sophon, ovvero di permettere a tanti utenti di utilizzare `Jupyter`_ su un server remoto, ma ha funzionalità di autorizzazione molto semplici e non ha supporto per :ref:`collaborazione` in tempo reale, in quanto i server `Jupyter`_ che istanzia sono single-user. + +È però più facile da scalare per grandi numeri di utenti, e ha più opzioni di deployment, a differenza di Sophon, che ne supporta una sola. + +.. _JupyterHub: https://jupyter.org/hub +.. _Jupyter: https://jupyter.org/ + + +Differenze da Google Colab +========================== + +`Google Colab`_ è un progetto che permette di effettuare ricerca su server `Jupyter`_ utilizzando le risorse della `Google Cloud Platform`_. + +A differenza di Sophon, è disponibile esclusivamente come `software-as-a-service`_, il che costringe agli utenti a trasmettere le loro informazioni ai server di Google, e non ha alcun tipo di supporto alla :ref:`collaborazione` in tempo reale. + +.. _Google Colab: https://colab.research.google.com/# +.. _Google Cloud Platform: https://cloud.google.com/ +.. _software-as-a-service: https://it.wikipedia.org/wiki/Software_as_a_service diff --git a/report/source/3_dev/4_tests/index.rst b/report/source/3_dev/4_tests/index.rst new file mode 100644 index 0000000..4599148 --- /dev/null +++ b/report/source/3_dev/4_tests/index.rst @@ -0,0 +1,130 @@ +Test effettuati +=============== + +Per motivi di tempo necessario, sono state selezionate solo alcune parti di codice su cui effettuare test. + + +Tutti i viewset di :py:mod:`sophon.core` +---------------------------------------- +.. default-domain:: py +.. default-role:: py:obj +.. module:: sophon.core.tests + + +Test case generici +^^^^^^^^^^^^^^^^^^ + +Vengono definiti alcuni test case generici per facilitare le interazioni tra ``APITestCase`` e viewset. + +.. note:: + + I nomi delle funzioni usano nomi con capitalizzazione inconsistente in quanto lo stesso modulo `unittest` non rispetta lo stile suggerito in :pep:`8`. + +.. class:: BetterAPITestCase(APITestCase) + + .. method:: as_user(self, username: str, password: str = None) -> typing.ContextManager[None] + + Context manager che permette di effettuare richieste all'API come uno specifico utente, effettuando il logout quando sono state effettuate le richieste necessarie. + + .. method:: assertData(self, data: ReturnDict, expected: dict) + + Asserzione che permette di verificare che l'oggetto restituito da una richiesta all'API contenga almeno le chiavi e i valori contenuti nel dizionario ``expected``. + +.. class:: ReadSophonTestCase(BetterAPITestCase, metaclass=abc.ABCMeta) + + Classe **astratta** che implementa metodi per testare rapidamente le azioni di un `.views.ReadSophonViewSet`. + + .. classmethod:: get_basename(cls) -> str + + Metodo **astratto** che deve restituire il basename del viewset da testare. + + .. classmethod:: get_url(cls, kind: str, *args, **kwargs) -> str + + Metodo utilizzato dal test case per trovare gli URL ai quali possono essere effettuate le varie azioni. + + I seguenti metodi permettono di effettuare azioni sul viewset: + + .. method:: list(self) -> rest_framework.response.Response + .. method:: retrieve(self, pk) -> rest_framework.response.Response + .. method:: custom_list(self, method: str, action: str, data: dict = None) -> rest_framework.response.Response + .. method:: custom_detail(self, method: str, action: str, pk, data: dict = None) -> rest_framework.response.Response + + I seguenti metodi asseriscono che una determinata azione con determinati parametri risponderà con il codice di stato ``code``, e restituiscono i dati contenuti nella risposta se l'azione è riuscita (``200 <= code < 300``) + + .. method:: assertActionList(self, code: int = 200) -> typing.Optional[ReturnDict] + .. method:: assertActionRetrieve(self, pk, code: int = 200) -> typing.Optional[ReturnDict] + .. method:: assertActionCustomList(self, method: str, action: str, data: dict = None, code: int = 200) -> typing.Optional[ReturnDict] + .. method:: assertActionCustomDetail(self, method: str, action: str, pk, data: dict = None, code: int = 200) -> typing.Optional[ReturnDict] + + +.. class:: WriteSophonTestCase(ReadSophonTestCase, metaclass=abc.ABCMeta) + + Classe **astratta** che estende `.ReadSophonTestCase` con le azioni di un `.views.WriteSophonViewSet`. + + .. method:: create(self, data) -> rest_framework.response.Response + .. method:: update(self, pk, data) -> rest_framework.response.Response + .. method:: destroy(self, pk) -> rest_framework.response.Response + + .. method:: assertActionCreate(self, data, code: int = 201) -> typing.Optional[ReturnDict] + .. method:: assertActionUpdate(self, pk, data, code: int = 200) -> typing.Optional[ReturnDict] + .. method:: assertActionDestroy(self, pk, code: int = 200) -> typing.Optional[ReturnDict] + + +Test case concreti +^^^^^^^^^^^^^^^^^^ + +Vengono testate tutte le view dell'app tramite `.BetterAPITestCase` e tutti i viewset dell'app tramite `.ReadSophonTestCase` e `WriteSophonTestCase`. + +.. class:: UsersByIdTestCase(ReadSophonTestCase) +.. class:: UsersByUsernameTestCase(ReadSophonTestCase) +.. class:: ResearchGroupTestCase(WriteSophonTestCase) +.. class:: SophonInstanceDetailsTestCase(BetterAPITestCase) + + +Alcune interazioni di `sophon.notebooks` +---------------------------------------- +.. default-domain:: py +.. default-role:: py:obj +.. module:: sophon.notebooks.tests + +Vengono definiti alcuni test case per alcune interazioni dell'app `sophon.notebooks`. + +.. class:: JupyterTestCase(TestCase) + + Test case che testa la generazione dei token per Jupyter. + +.. class:: ApacheTestCase(TestCase) + + Test case che testa la conversione in `bytes` per la rubrica `dbm` del :ref:`modulo proxy`. + + +Alcune interazioni complicate del frontend +------------------------------------------ +.. default-domain:: js +.. default-role:: js:class + +Vengono infine definiti test case per alcune interazioni ritenute particolarmente complesse del frontend. + + +Encoding dell'URL dell'istanza nell'URL della pagina +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- encodes pathless URL +- encodes URL with port number +- encodes URL with simple path +- encodes URL with colon in path +- does not encode URL with ``%3A`` in path +- decodes pathless URL +- decodes URL with port number +- decodes URL with simple path +- decodes URL with colon in path + + +Parsing dei segmenti del path +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- parses empty path +- parses instance path +- parses research group path +- parses research project path +- parses notebook path diff --git a/report/source/3_dev/5_license/index.rst b/report/source/3_dev/5_license/index.rst new file mode 100644 index 0000000..a7eb7e4 --- /dev/null +++ b/report/source/3_dev/5_license/index.rst @@ -0,0 +1,12 @@ +Licenza +******* + +Sophon è rilasciato sotto la `GNU Affero General Public License 3`_ (o successiva). + +Il testo completo della licenza è disponibile all'interno del file `LICENSE.txt`_ allegato al codice sorgente del software. + +Si specifica che la licenza copre tutti i file all'interno del repository ``Steffo99/sophon``, anche se essi non contengono un header che indica che sono protetti da copyright. + + +.. _GNU Affero General Public License 3: https://www.gnu.org/licenses/agpl-3.0.html +.. _LICENSE.txt: https://github.com/Steffo99/sophon/blob/main/LICENSE.txt diff --git a/docs/source/_static/group_delete_confirm.mp4 b/report/source/_static/group_delete_confirm.mp4 similarity index 100% rename from docs/source/_static/group_delete_confirm.mp4 rename to report/source/_static/group_delete_confirm.mp4 diff --git a/report/source/conf.py b/report/source/conf.py new file mode 100644 index 0000000..baa249e --- /dev/null +++ b/report/source/conf.py @@ -0,0 +1,148 @@ +# Customized Sphinx configuration +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +import datetime + +import pkg_resources + +# Project name +project = 'Sophon' +# Project author +author = 'Stefano Pigozzi' +# Project copyright +project_copyright = f'{datetime.date.today().year}, {author}' +# Project short version +version = pkg_resources.get_distribution(project.lower()).version +# Project long version +release = pkg_resources.get_distribution(project.lower()).version + +# Sphinx language +language = "en" # TODO: Change to it for thesis +# Sphinx extensions +extensions = [ + "sphinx.ext.intersphinx", + "sphinx.ext.autosectionlabel", # TODO: Remove in thesis +] + +# Source files encoding +source_encoding = "UTF-8" +# Source file extensions +source_suffix = { + ".rst": "restructuredtext", +} +# Source files parsers +source_parsers = {} + +# The doc from which to start rendering +root_doc = "index" +# Files to ignore when rendering +exclude_patterns = [ + "build", + "_build", + "Thumbs.db", + ".DS_Store", +] +# Sphinx template files +templates_path = [ + '_templates', +] + +# Prologue of all rst files +rst_prolog = "" +# Epilogue of all rst files +rst_epilog = "" + +# Default domain +primary_domain = None +# Default role +default_role = None + +# Print warnings on the page +keep_warnings = False +# Display more warnings than usual +nitpicky = False + +# Intersphinx URLs +intersphinx_mapping = { + "python": ("https://docs.python.org/3.8", None), + "django": ("http://docs.djangoproject.com/en/3.2/", "http://docs.djangoproject.com/en/3.2/_objects/"), + "docker": ("https://docker-py.readthedocs.io/en/stable/", None), + "coloredlogs": ("https://coloredlogs.readthedocs.io/en/latest/", None), +} +# Manpages URL +manpages_url = "https://man.archlinux.org/" + +# Autonumber figures +numfig = False # TODO: Set to true for thesis +# Autonumeration formatting +numfig_format = { + "figure": "Fig. %s", # TODO: Translate in italian + "table": "Table %s", # TODO: Translate in italian + "code-block": "Listing %s", # TODO: Translate in italian + "section": "Section %s", # TODO: Translate in italian +} +# Maximum depth for autonumeration +numfig_secnum_depth = 2 + +# HTML builder theme +html_theme = 'sphinx_rtd_theme' +# Configuration for the theme +html_theme_options = { + "style_nav_header_background": "#051836", + "github_url": "https://github.com/Steffo99/sophon/tree/main/docs/source", +} +# Title of the HTML page +html_title = f"{project}" +# Short title of the HTML page +html_short_title = f"{project}" +# Path of the documentation static files +html_static_path = [ + "_static", +] +# Path of extra files to add to the build +html_extra_path = [ + "_extra", +] + +# LaTeX rendering engine to use +latex_engine = "pdflatex" +# LaTeX top level title type +latex_toplevel_sectioning = "part" +# LaTeX URLs rendering +latex_show_urls = "footnote" +# LaTeX theme +latex_theme = "manual" # TODO: I'm not sure between manual or howto + +latex_setup = { + "TitleColor": "{rgb}{0,0,0.08}", + + "InnerLinkColor": "{rgb}{0.19,0.57,0.82}", + "OuterLinkColor": "{rgb}{0.19,0.57,0.82}", + + "VerbatimBorderColor": "{rgb}{0.88,0.88,0.88}", + "VerbatimColor": "{rgb}{0.97,0.97,0.97}", + + "noteBorderColor": "{rgb}{0.42,0.69,0.87}", + "importantBorderColor": "{rgb}{0.42,0.69,0.87}", + + "hintBorderColor": "{rgb}{0.1,0.74,0.61}", + "tipBorderColor": "{rgb}{0.1,0.74,0.61}", + + "warningBorderColor": "{rgb}{0.94,0.7,0.49}", + "warningBgColor": "{rgb}{1,0.93,0.8}", + "cautionBorderColor": "{rgb}{0.94,0.7,0.49}", + "cautionBgColor": "{rgb}{1,0.93,0.8}", + "attentionBorderColor": "{rgb}{0.94,0.7,0.49}", + "attentionBgColor": "{rgb}{1,0.93,0.8}", + + "dangerBorderColor": "{rgb}{0.95,0.62,0.59}", + "dangerBgColor": "{rgb}{0.95,0.62,0.59}", + "errorBorderColor": "{rgb}{0.95,0.62,0.59}", + "errorBgColor": "{rgb}{0.95,0.62,0.59}", +} +latex_elements = { + # TODO: Set Times New Roman font + "papersize": "a4paper", + "pointsize": "12pt", + "sphinxsetup": ", ".join(f"{key}={value}" for key, value in latex_setup.items()) +} diff --git a/report/source/index.rst b/report/source/index.rst new file mode 100644 index 0000000..8991c0c --- /dev/null +++ b/report/source/index.rst @@ -0,0 +1,46 @@ +Sophon +###### + +Benvenuto alla documentazione di Sophon, il centro di ricerca per le Università! + +È divisa in tre parti: un **manuale utente** che illustra i concetti chiave che un utente di Sophon deve sapere per utilizzarlo, una **guida per l'amministratore** che fornisce le conoscenze necessarie al deployment del software, e infine una **documentazione tecnica** per i programmatori interessati a capire il funzionamento a livello di codice dell'applicazione. + +Si è cercato di mantenere il registro di ciascuna parte al livello tecnico del pubblico a cui è destinata, pertanto è possibile osservare alcune **semplificazioni** nelle prime parti. + + +.. toctree:: + :caption: Manuale utente + :maxdepth: 2 + + 1_user/1_about/index + 1_user/2_concepts/index + 1_user/3_extras/index + + +.. toctree:: + :caption: Guida per l'amministratore + :maxdepth: 2 + + 2_admin/1_installation/index + 2_admin/2_administration/index + 2_admin/3_update/index + 2_admin/4_uninstallation/index + + +.. toctree:: + :caption: Documentazione tecnica + :maxdepth: 2 + + 3_dev/1_tools/index + 3_dev/2_structure/index + 3_dev/3_differences/index + 3_dev/4_tests/index + 3_dev/5_license/index + + +Pagine speciali +=============== + +- :ref:`genindex` +- :ref:`modindex` +- :ref:`search` diff --git a/thesis/.gitattributes b/thesis/.gitattributes new file mode 100644 index 0000000..f8ff2b5 --- /dev/null +++ b/thesis/.gitattributes @@ -0,0 +1 @@ +*.mp4 filter=lfs diff=lfs merge=lfs -text diff --git a/thesis/Makefile b/thesis/Makefile new file mode 100644 index 0000000..b526431 --- /dev/null +++ b/thesis/Makefile @@ -0,0 +1,25 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + + +livehtml: + sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/thesis/make.bat b/thesis/make.bat new file mode 100644 index 0000000..061f32f --- /dev/null +++ b/thesis/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/thesis/source/_static/group_delete_confirm.mp4 b/thesis/source/_static/group_delete_confirm.mp4 new file mode 100644 index 0000000..06ab00f --- /dev/null +++ b/thesis/source/_static/group_delete_confirm.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f4a834868c351f5cfaf99c7f78c2ed5b7aaa458fe444c69a3d0c9c1c56ab0993 +size 75562 diff --git a/docs/source/conf.py b/thesis/source/conf.py similarity index 100% rename from docs/source/conf.py rename to thesis/source/conf.py diff --git a/docs/source/docs/1_sinossi/index.rst b/thesis/source/docs/1_sinossi/index.rst similarity index 100% rename from docs/source/docs/1_sinossi/index.rst rename to thesis/source/docs/1_sinossi/index.rst diff --git a/thesis/source/docs/1_sinossi/screenshot.png b/thesis/source/docs/1_sinossi/screenshot.png new file mode 100644 index 0000000..36e1bda --- /dev/null +++ b/thesis/source/docs/1_sinossi/screenshot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a684f2d0ad14db1bf77e5b0837f69d9fb25e4cfbd44aaf5df3d756b421838729 +size 95898 diff --git a/docs/source/docs/2_introduzione/index.rst b/thesis/source/docs/2_introduzione/index.rst similarity index 100% rename from docs/source/docs/2_introduzione/index.rst rename to thesis/source/docs/2_introduzione/index.rst diff --git a/docs/source/docs/3_presentazione/index.rst b/thesis/source/docs/3_presentazione/index.rst similarity index 100% rename from docs/source/docs/3_presentazione/index.rst rename to thesis/source/docs/3_presentazione/index.rst diff --git a/docs/source/docs/4_requisiti/index.rst b/thesis/source/docs/4_requisiti/index.rst similarity index 100% rename from docs/source/docs/4_requisiti/index.rst rename to thesis/source/docs/4_requisiti/index.rst diff --git a/docs/source/docs/5_progetto/index.rst b/thesis/source/docs/5_progetto/index.rst similarity index 100% rename from docs/source/docs/5_progetto/index.rst rename to thesis/source/docs/5_progetto/index.rst diff --git a/docs/source/docs/6_implementazione/index.rst b/thesis/source/docs/6_implementazione/index.rst similarity index 100% rename from docs/source/docs/6_implementazione/index.rst rename to thesis/source/docs/6_implementazione/index.rst diff --git a/docs/source/docs/6_implementazione/tech.rst b/thesis/source/docs/6_implementazione/tech.rst similarity index 100% rename from docs/source/docs/6_implementazione/tech.rst rename to thesis/source/docs/6_implementazione/tech.rst diff --git a/docs/source/docs/7_applicazione/index.rst b/thesis/source/docs/7_applicazione/index.rst similarity index 100% rename from docs/source/docs/7_applicazione/index.rst rename to thesis/source/docs/7_applicazione/index.rst diff --git a/docs/source/docs/8_conclusione/index.rst b/thesis/source/docs/8_conclusione/index.rst similarity index 100% rename from docs/source/docs/8_conclusione/index.rst rename to thesis/source/docs/8_conclusione/index.rst diff --git a/docs/source/docs/9_appendice/index.rst b/thesis/source/docs/9_appendice/index.rst similarity index 100% rename from docs/source/docs/9_appendice/index.rst rename to thesis/source/docs/9_appendice/index.rst diff --git a/docs/source/index.rst b/thesis/source/index.rst similarity index 100% rename from docs/source/index.rst rename to thesis/source/index.rst diff --git a/docs/source/refs.bib b/thesis/source/refs.bib similarity index 100% rename from docs/source/refs.bib rename to thesis/source/refs.bib