├── .github └── workflows │ └── build.yml ├── .gitignore ├── LICENSE ├── README.md ├── build_deb.sh ├── build_docs.sh ├── build_iso.sh ├── deb ├── .gitignore └── DEBIAN │ ├── control │ ├── install │ └── postinst ├── docs ├── Makefile ├── _static │ ├── LICENSE │ ├── doctools.js │ ├── documentation_options.js │ ├── pygments.css │ ├── sphinx_highlight.js │ ├── theme.css │ └── theme.js ├── conf.py ├── index.rst ├── make.bat ├── modules │ ├── addons.rst │ ├── general_administration.rst │ ├── libre-workspace-portal.rst │ └── nextcloud.rst └── setup │ ├── folder-structure.rst │ ├── installation.rst │ └── introduction.rst ├── download_debian_iso.sh ├── libre-workspace-logo.svg ├── libre_workspace_header.png ├── linux-arbeitsplatz.deb ├── preseed.cfg ├── run_development.sh ├── splash.png ├── src ├── etc │ └── libre-workspace │ │ ├── .gitignore │ │ ├── libre-workspace.env.example │ │ └── portal │ │ ├── .gitignore │ │ └── portal.conf.example ├── join_scripts │ └── linux-client │ │ ├── desktop │ │ └── join_libre_workspace.py │ │ └── join_realm.sh └── usr │ ├── bin │ ├── libre-workspace-add-oidc-client │ ├── libre-workspace-generate-secret │ ├── libre-workspace-portal │ ├── libre-workspace-remove-oidc-client │ ├── libre-workspace-remove-webserver-entry │ ├── libre-workspace-reset-2fa │ ├── libre-workspace-send-mail │ ├── libre-workspace-service │ └── libre-workspace-set-local-admin-password │ └── lib │ ├── libre-workspace │ ├── modules │ │ ├── collabora │ │ │ ├── caddy_collabora_entry.txt │ │ │ ├── remove_collabora.sh │ │ │ ├── setup_collabora.sh │ │ │ └── update_collabora.sh │ │ ├── desktop │ │ │ ├── administration │ │ │ │ ├── add_user.sh │ │ │ │ └── remove_user.sh │ │ │ ├── docker-compose.yml │ │ │ ├── guacamole_version.sh │ │ │ ├── remove_desktop.sh │ │ │ ├── scripts │ │ │ │ ├── auto_logout.sh │ │ │ │ └── setup_user_desktop.sh │ │ │ ├── setup_desktop.sh │ │ │ └── update_desktop.sh │ │ ├── jitsi │ │ │ ├── caddy_jitsi_entry.txt │ │ │ ├── remove_jitsi.sh │ │ │ ├── setup_jitsi.sh │ │ │ └── update_jitsi.sh │ │ ├── matrix │ │ │ ├── docker_matrix_entry.txt │ │ │ ├── remove_matrix.sh │ │ │ ├── setup_matrix.sh │ │ │ ├── update_element_config.sh │ │ │ ├── update_env.sh │ │ │ └── update_matrix.sh │ │ ├── nextcloud │ │ │ ├── caddy_nextcloud_entry.txt │ │ │ ├── patches │ │ │ │ ├── 2024-06-25_install_pdo_sqlite.sh │ │ │ │ ├── 2024-06-25_move_to_apt_redis.sh │ │ │ │ └── 2024-08-01_fix_localhost_trusted_domains.sh │ │ │ ├── remove_nextcloud.sh │ │ │ ├── setup_nextcloud.sh │ │ │ ├── update_env.sh │ │ │ └── update_nextcloud.sh │ │ ├── onlyoffice │ │ │ ├── caddy_onlyoffice_entry.txt │ │ │ ├── remove_onlyoffice.sh │ │ │ ├── setup_onlyoffice.sh │ │ │ ├── update_env.sh │ │ │ └── update_onlyoffice.sh │ │ ├── samba_dc │ │ │ ├── patches │ │ │ │ └── 2024-12-14_mark_samba_dc_installed.sh │ │ │ ├── remove_samba_dc.sh │ │ │ ├── setup_samba_dc.sh │ │ │ └── update_samba_dc.sh │ │ └── xfce │ │ │ ├── remove_xfce.sh │ │ │ ├── setup_xfce.sh │ │ │ ├── update_env.sh │ │ │ └── update_xfce.sh │ └── portal │ │ ├── addon_creator │ │ ├── __init__.py │ │ ├── addon_template │ │ │ ├── LICENSE │ │ │ ├── addon.conf │ │ │ ├── control │ │ │ ├── install │ │ │ ├── postinst │ │ │ ├── remove_addon.sh │ │ │ ├── setup_addon.sh │ │ │ └── update_addon.sh │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── migrations │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── tests.py │ │ ├── urls.py │ │ ├── utils.py │ │ └── views.py │ │ ├── app_dashboard │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── cards.py │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_dashboardentry_icon_url_dashboardentry_is_system.py │ │ │ ├── 0003_dashboardentry_groups.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── settings.py │ │ ├── templates │ │ │ └── app_dashboard │ │ │ │ ├── app_dashboard_entries.html │ │ │ │ └── index.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ │ ├── idm │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── challenges.py │ │ ├── forms.py │ │ ├── idm.py │ │ ├── ldap.py │ │ ├── migrations │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── oidc_provider_settings.py │ │ ├── templates │ │ │ ├── idm │ │ │ │ ├── add_new_totp_device.html │ │ │ │ ├── admin │ │ │ │ │ ├── assign_groups_to_user.html │ │ │ │ │ ├── assign_users_to_group.html │ │ │ │ │ ├── create_group.html │ │ │ │ │ ├── edit_group.html │ │ │ │ │ ├── edit_user.html │ │ │ │ │ ├── group_overview.html │ │ │ │ │ └── user_overview.html │ │ │ │ ├── change_password.html │ │ │ │ ├── dashboard.html │ │ │ │ ├── libre_workspace_challenges.html │ │ │ │ ├── login.html │ │ │ │ ├── reset_password.html │ │ │ │ └── user_settings.html │ │ │ └── oidc_provider │ │ │ │ ├── authorize.html │ │ │ │ ├── end_session_prompt.html │ │ │ │ └── error.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ │ ├── install.sh │ │ ├── lac │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── static │ │ │ └── lac │ │ │ │ ├── css │ │ │ │ ├── pico.min.css │ │ │ │ └── pico.min.css.map │ │ │ │ ├── icons │ │ │ │ ├── LICENSE │ │ │ │ ├── MaterialIcons-Regular.ttf │ │ │ │ ├── company.webp │ │ │ │ ├── desktop.webp │ │ │ │ ├── element.webp │ │ │ │ ├── jitsi.webp │ │ │ │ ├── libre-workspace.png │ │ │ │ ├── libre-workspace.webp │ │ │ │ ├── lock.webp │ │ │ │ ├── nextcloud.webp │ │ │ │ └── xfce.png │ │ │ │ ├── images │ │ │ │ ├── background-2.webp │ │ │ │ ├── background-blured.webp │ │ │ │ ├── background.webp │ │ │ │ ├── desktop.jpg │ │ │ │ └── desktop_remote.jpg │ │ │ │ └── js │ │ │ │ ├── jquery-3.7.1.min.js │ │ │ │ └── modal.js │ │ ├── templates.py │ │ ├── templates │ │ │ └── lac │ │ │ │ ├── base.html │ │ │ │ ├── confirm.html │ │ │ │ ├── create_x.html │ │ │ │ ├── edit_x.html │ │ │ │ ├── generic_form.html │ │ │ │ ├── message.html │ │ │ │ ├── overview_x.html │ │ │ │ └── robots.txt │ │ ├── urls.py │ │ └── wsgi.py │ │ ├── m23software │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── connector.py │ │ ├── forms.py │ │ ├── migrations │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ │ ├── manage.py │ │ ├── openbox-autostart │ │ ├── prepare_for_first_boot.sh │ │ ├── requirements.txt │ │ ├── unix │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── email.py │ │ ├── forms.py │ │ ├── migrations │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── templates │ │ │ └── unix │ │ │ │ ├── backup_dashboard.html │ │ │ │ ├── backup_settings.html │ │ │ │ ├── critical_system_configuration.html │ │ │ │ ├── data_export.html │ │ │ │ ├── data_import.html │ │ │ │ ├── data_management.html │ │ │ │ ├── email_configuration.html │ │ │ │ ├── file_explorer.html │ │ │ │ ├── folder_view.html │ │ │ │ ├── module_management.html │ │ │ │ ├── mounting.html │ │ │ │ ├── pick_folder.html │ │ │ │ ├── system_configuration.html │ │ │ │ ├── system_dashboard.html │ │ │ │ ├── system_management.html │ │ │ │ └── update_management.html │ │ ├── tests.py │ │ ├── unix_scripts │ │ │ ├── .gitignore │ │ │ ├── cfg.py │ │ │ ├── do_data_export.sh │ │ │ ├── general │ │ │ │ ├── basics.sh │ │ │ │ ├── install.sh │ │ │ │ ├── patches │ │ │ │ │ ├── 2024-08-01_dns_forwarder_only.sh │ │ │ │ │ ├── 2024-12-13_ignore_admin_users_nextcloud.sh │ │ │ │ │ └── 2025_05_09_fix_fail2ban_ond_deb12.sh │ │ │ │ ├── setup_internal_https.sh │ │ │ │ ├── setup_rest_of_libre-workspace.sh │ │ │ │ └── update_email_settings.py │ │ │ ├── get_ip.sh │ │ │ ├── import_folder_to_nextcloud_user.sh │ │ │ ├── maintenance │ │ │ │ ├── .gitignore │ │ │ │ ├── cleanup.sh │ │ │ │ ├── do_backup.sh │ │ │ │ ├── do_update.sh │ │ │ │ ├── mount_backups.sh │ │ │ │ ├── recover_path.sh │ │ │ │ ├── start_services.sh │ │ │ │ ├── stop_services.sh │ │ │ │ ├── umount_backups.sh │ │ │ │ └── update_everything.sh │ │ │ ├── service.py │ │ │ ├── unix.py │ │ │ ├── unix_config.py │ │ │ └── utils.py │ │ ├── urls.py │ │ └── views.py │ │ ├── update_libre_workspace.sh │ │ └── welcome │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── migrations │ │ └── __init__.py │ │ ├── models.py │ │ ├── templates │ │ └── welcome │ │ │ ├── .gitignore │ │ │ ├── access.html │ │ │ ├── installation_running.html │ │ │ ├── libreworkspace_lite.html │ │ │ ├── welcome_dns_settings.html │ │ │ ├── welcome_select_apps.html │ │ │ └── welcome_start.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ └── systemd │ └── system │ ├── libre-workspace-portal.service │ └── libre-workspace-service.service └── tests └── oidc └── index.html /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | name: Deb 7 | 8 | on: 9 | push: 10 | branches: [ "main" ] 11 | pull_request: 12 | branches: [ "main" ] 13 | 14 | jobs: 15 | build: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v4 19 | - run: bash build_deb.sh 20 | - name: Upload deb 21 | uses: actions/upload-artifact@v4 22 | with: 23 | name: libre-workspace-deb 24 | path: libre-workspace.deb -------------------------------------------------------------------------------- /build_deb.sh: -------------------------------------------------------------------------------- 1 | # Copy the files to the debian package structure 2 | cp -r src/usr deb/ 3 | cp -r src/etc deb/ 4 | 5 | # Disable DEBUG mode 6 | sed -i "s/DEBUG = True/DEBUG = False/g" deb/usr/lib/libre-workspace/portal/lac/settings.py 7 | # Disable Admin site (ADMIN_ENABLED) 8 | sed -i "s/ADMIN_ENABLED = True/ADMIN_ENABLED = False/g" deb//usr/lib/libre-workspace/portal/lac/settings.py 9 | 10 | chmod +x deb/usr/lib/libre-workspace/portal/install.sh 11 | chmod +x deb/usr/bin/* 12 | 13 | chmod 755 deb/DEBIAN 14 | chmod 755 deb/DEBIAN/postinst 15 | 16 | dpkg-deb --build -Zxz --root-owner-group deb 17 | mv deb.deb libre-workspace.deb 18 | 19 | echo "!!!Ensure that you build the deb package from a fresh cloned repository! (Otherwise some control files might disturb linux-arbeitplatz later)!!!" -------------------------------------------------------------------------------- /build_docs.sh: -------------------------------------------------------------------------------- 1 | cd docs 2 | make clean html 3 | -------------------------------------------------------------------------------- /build_iso.sh: -------------------------------------------------------------------------------- 1 | arch="amd" 2 | 3 | # Prepare working files for manipulating iso file 4 | mkdir ORIGISO 5 | mkdir NEWISO 6 | mount -o loop debian-original.iso ./ORIGISO 7 | cp -rT ./ORIGISO/ ./NEWISO/ 8 | umount ./ORIGISO 9 | 10 | # Write preseed.cfg and graphic into new iso 11 | chmod +w -R ./NEWISO/install.$arch/ 12 | gunzip ./NEWISO/install.$arch/gtk/initrd.gz 13 | echo preseed.cfg | cpio -H newc -o -A -F ./NEWISO/install.$arch/gtk/initrd 14 | 15 | # Extraxt initrd.gz 16 | cd ./NEWISO/install.$arch/gtk/ 17 | mkdir tmp && cd tmp 18 | cpio -i -F ../initrd -d 19 | 20 | # Overwrite libre workspace header with debian header 21 | cd ../../../../ 22 | cp libre_workspace_header.png ./NEWISO/install.$arch/gtk/tmp/usr/share/graphics/logo_debian.png 23 | cd ./NEWISO/install.$arch/gtk/tmp 24 | 25 | # Repack initrd.gz 26 | rm ../initrd 27 | find . | cpio -o -H newc -F ../initrd 28 | cd ../../../../ 29 | rm -rf ./NEWISO/install.$arch/gtk/tmp 30 | gzip ./NEWISO/install.$arch/gtk/initrd 31 | chmod -w -R ./NEWISO/install.$arch 32 | 33 | # Copy the custom package (which does the installation of libre-workspace in the end) to the new iso 34 | cp libre-workspace.deb ./NEWISO/ 35 | 36 | # Change the boot menu to automatically start the installation 37 | sed -i "s/timeout 300/timeout 1/g" ./NEWISO/isolinux/spkgtk.cfg 38 | sed -i "s/speakup.synth=soft //g" ./NEWISO/isolinux/spkgtk.cfg 39 | 40 | # Change the installer graphic to the one from libre workspace 41 | cp splash.png ./NEWISO/isolinux/splash.png 42 | 43 | # Generate new md5sums 44 | chmod +w ./NEWISO/md5sum.txt 45 | cd NEWISO 46 | find -follow -type f ! -name md5sum.txt -print0 | xargs -0 md5sum > ./md5sum.txt 47 | chmod -w ./md5sum.txt 48 | cd .. 49 | 50 | # Generate new iso image 51 | genisoimage -r -J -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e boot/grub/efi.img -no-emul-boot -o libre-workspace.iso ./NEWISO 52 | isohybrid --uefi libre-workspace.iso 53 | rm -rf ./ORIGISO ./NEWISO -------------------------------------------------------------------------------- /deb/.gitignore: -------------------------------------------------------------------------------- 1 | usr/* 2 | etc/* -------------------------------------------------------------------------------- /deb/DEBIAN/control: -------------------------------------------------------------------------------- 1 | Package: libre-workspace-portal 2 | Version: 0.10.0 3 | Depends: libldap2-dev, python3-venv, libsasl2-dev, caddy, gcc, python3-dev, borgbackup, python-llfuse | python3-llfuse, rsync, zip, cron, unzip, sudo, git 4 | Maintainer: Jean28518 5 | Architecture: all 6 | Homepage: https://libre-workspace.org 7 | Section: admin 8 | Description: Libre Workspace Management Software 9 | Installed-Size: 0 10 | Replaces: linux-arbeitsplatz 11 | -------------------------------------------------------------------------------- /deb/DEBIAN/install: -------------------------------------------------------------------------------- 1 | usr 2 | etc -------------------------------------------------------------------------------- /deb/DEBIAN/postinst: -------------------------------------------------------------------------------- 1 | if [ "$CLEAN_CADDYFILE" = "True" ]; then 2 | /usr/bin/echo "" > /etc/caddy/Caddyfile 3 | fi 4 | 5 | /bin/bash /usr/lib/libre-workspace/portal/install.sh 6 | 7 | /usr/bin/systemctl daemon-reload 8 | /usr/bin/systemctl enable libre-workspace-portal.service --now 9 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | const DOCUMENTATION_OPTIONS = { 2 | VERSION: '', 3 | LANGUAGE: 'en', 4 | COLLAPSE_INDEX: false, 5 | BUILDER: 'dirhtml', 6 | FILE_SUFFIX: '.html', 7 | LINK_SUFFIX: '.html', 8 | HAS_SOURCE: true, 9 | SOURCELINK_SUFFIX: '.txt', 10 | NAVIGATION_WITH_KEYS: false, 11 | SHOW_SEARCH_SUMMARY: true, 12 | ENABLE_SEARCH_SHORTCUTS: true, 13 | }; -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # For the full list of built-in configuration values, see the documentation: 4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 5 | 6 | # -- Project information ----------------------------------------------------- 7 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information 8 | 9 | project = 'libre-workspace' 10 | copyright = '2023, Jean28518' 11 | author = 'Jean28518' 12 | 13 | # -- General configuration --------------------------------------------------- 14 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 15 | 16 | extensions = [] 17 | 18 | templates_path = ['_templates'] 19 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 20 | 21 | 22 | 23 | # -- Options for HTML output ------------------------------------------------- 24 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 25 | 26 | html_theme = 'press' 27 | html_static_path = ['_static'] 28 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ************************************************** 2 | Libre Workspace Documentation (for Administrators) 3 | ************************************************** 4 | 5 | 6 | .. toctree:: 7 | :maxdepth: 2 8 | :caption: Setup 9 | 10 | setup/introduction 11 | setup/installation 12 | 13 | .. toctree:: 14 | :maxdepth: 2 15 | :caption: Modules 16 | 17 | modules/general_administration 18 | modules/libre-workspace-portal 19 | modules/nextcloud 20 | modules/addons 21 | 22 | 23 | 24 | Indices and tables 25 | ================== 26 | 27 | * :ref:`genindex` 28 | * :ref:`modindex` 29 | * :ref:`search` 30 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/modules/nextcloud.rst: -------------------------------------------------------------------------------- 1 | ********* 2 | Nextcloud 3 | ********* 4 | 5 | Nextcloud is one of the main modules of libre workspace. 6 | It is deployed directly on the server with php, mariadb, and caddy as a webserver. 7 | 8 | Also all recommended php options are enabled and all recommended php modules are installed. 9 | The automated installer of libre workspace doesn't setup a memory cache for php. 10 | If you want to setup a memory cache redis is recommended. 11 | 12 | Nextcloud is installed in the directory ``/var/www/nextcloud``. 13 | 14 | Online Office 15 | ============= 16 | 17 | As online office libre workspace uses whether Collabora Online or OnlyOffice. 18 | These are deployed via simple docker files and docker-compose. 19 | The configuration for that is in ``/root/``. 20 | 21 | How to update 22 | ============= 23 | 24 | You can easily update nextcloud via the web interface or enabling the automatic updates for it in the libre workspace portal. 25 | Please have in mind that on old servers (or php versions) nextcloud will not work anymore after an update because of the php version. 26 | In this case you have to update php first and/or the server itself. 27 | 28 | The docker tag of Collabora Online and OnlyOffice is ``latest``. 29 | You can also enable automatic updates for the docker containers in the libre workspace portal, which is highly recommended. 30 | Otherwise you can easily remove the corresponding docker container and start the deployment process via the run.sh files in ``/root/`` again. 31 | 32 | Can I also integrate an existing Nextcloud to libre workspace? 33 | ============================================================== 34 | 35 | Yes, of course this is possible! If your nextcloud is installed in the directory ``/var/www/nextcloud`` then nothing has to be done, that libre workspace can work with it. Otherwise an ``ln -s`` is recommended. 36 | If the nextcloud instance is installed at another server you can also integrate it to libre workspace. e.g. with an caddy redirect or add a specific link at the libre workspace portal. 37 | 38 | It is not recommended to connect the user database of libre workspace with an existing nextcloud via e.g. ldap, or SSO because ldap and SSO are using an objectid for the nextcloud username (internally) so your existing users would be "changed" to new users. (Your data will not be lost, but the user will be "linked" to a new one.) 39 | 40 | You can also move (if you want) your existing nextcloud webserver to caddy, which is recommended for libre workspace. You can find the complete nextcloud caddy entry here: https://github.com/Jean28518/libre-workspace/blob/main/src/lac/unix/unix_scripts/nextcloud/caddy_nextcloud_entry.txt (You have to replace "SED_DOMAIN" with your real domain name.) 41 | 42 | 43 | Known issues 44 | ============ 45 | 46 | LDAP/AD-Integration Settings UI in Nextcloud is not working. 47 | ------------------------------------------------------------ 48 | 49 | This is because the "index.php" part of the URL is removed. 50 | But the LDAP/AD-Integration itself is working fine, it is set via occ. 51 | 52 | If you want to get the ui working you have to revert the changes which are listed here: 53 | -------------------------------------------------------------------------------- /docs/setup/folder-structure.rst: -------------------------------------------------------------------------------- 1 | ################################# 2 | New folder structure for Libre Workspace 3 | ################################# 4 | 5 | - New package name: ``libre-workspace-portal`` 6 | - Every addon is a seperate deb package 7 | 8 | - File Structure: 9 | 10 | - ``usr`` 11 | 12 | - ``lib`` 13 | 14 | - ``libre-workspace/portal`` 15 | 16 | - (Django project) 17 | - Folder: ``modules`` (inside are symlinks to the addon folders inside ``/usr/lib/libre-workspace/modules/``) 18 | 19 | - ``bin`` 20 | 21 | - ``libre-workspace-portal`` (bash script to run the django project, .env is in ``/var/lib/libre-workspace/portal/venv``) 22 | - ``libre-workspace-service`` (bash script to run the service.py``) 23 | - ``libre-workspace-generate-secret`` (with argument ``[length]``), it echoes a random string of the given length 24 | - ``libre-workspace-remove-webserver-entry`` (with argument of the subdomain) 25 | - ``libre-workspace-add-oidc-client`` (with arguments of name, client_id, client_secret, redirect_uri(s) (separated by commas)) 26 | - ``libre-workspace-remove-oidc-client`` (with argument of the name) 27 | - ``libre-workspace-send-mail`` 28 | - ``libre-workspace-set-local-admin-password`` (with argument of the password) 29 | - ``libre-workspace-reset-2fa`` (with argument of the username) 30 | 31 | - ``etc`` 32 | 33 | - ``libre-workspace`` 34 | 35 | - ``portal`` 36 | 37 | - ``portal.conf`` (new file for cfg) 38 | 39 | - ``libre-workspace.conf`` (new file for unix.conf) 40 | - ``libre-workspace.env`` (new file for env.sh) 41 | - ``modules`` 42 | 43 | - (later for module configuration, not yet used) 44 | 45 | - ``var`` 46 | 47 | - ``lib`` 48 | 49 | - ``libre-workspace/portal`` 50 | 51 | - history folder 52 | - control files of ``libre-workspace-portal`` 53 | - media folder 54 | - app dashboard settings 55 | - python venv 56 | -------------------------------------------------------------------------------- /docs/setup/introduction.rst: -------------------------------------------------------------------------------- 1 | ******************************* 2 | Introduction to Libre Workspace 3 | ******************************* 4 | 5 | Libre Workspace consists of a set of software packages which should implement a modern cloud infrastructure for small companies or individuals. It is based on the following software: 6 | 7 | * `Debian `_ as the operating system 8 | * `Samba DC `_ as the domain controller and Active Directory implementation 9 | * `Libre Workspace Portal `_ as the central management software for the Libre Workspace 10 | * `Nextcloud `_ as the cloud storage solution with integrated groupware 11 | * `Jitsi Meet `_ as the video conferencing solution 12 | * `Matrix `_ as the chat solution (with `element `_ as the web client) 13 | * `BorgBackup `_ as the backup solution 14 | 15 | Features 16 | ======== 17 | The Libre Workspace is a complete solution for small companies or individuals. It provides the following features: 18 | 19 | * **Central management** of users, groups (and computers in the future) via the Libre Workspace Portal 20 | * **File storage and sharing** via Nextcloud 21 | * **Groupware (calendar, contacts, tasks, mail)** via Nextcloud 22 | * **Online Office** via Collabora Online or OnlyOffice (selectable in the Libre Workspace Portal) 23 | * **Video conferencing** via Jitsi Meet 24 | * **Chat** via Matrix (with the web client **element**) (Groupchats, Spaces, End-to-End Encryption, File Sharing, small Video Calls, Voice Calls, direct Messages, etc.) 25 | * **Backups of the whole system** via BorgBackup - With restore function via the Libre Workspace Portal 26 | * **Data import and export** via the Libre Workspace Portal 27 | * **Simple installation and configuration** via the Libre Workspace Portal 28 | * **Addon-Support** (e.g. for additional software like ERP, CRM, etc.) 29 | 30 | Limitations 31 | =========== 32 | All limitations are temporary and will be removed in the future. 33 | 34 | - At the current time the Libre Workspace is only available in German. 35 | - Currently the Libre Workspace automation is in BETA status. If you want to use it in production, feel free to contact us to get support: https://www.linuxguides.de/ 36 | - Currently we don't have an automated solution for mail. At the current time you have to use an external mail provider or setup your own mail server. 37 | 38 | You can setup the Libre Workspace on your own by following the instructions in this documentation via our automated installation. -------------------------------------------------------------------------------- /download_debian_iso.sh: -------------------------------------------------------------------------------- 1 | # Download the index.html of debian.org 2 | wget -O /tmp/debian-index.html https://www.debian.org/ 3 | 4 | #search for the line with https://*-amd64-netinst.iso and extract the link to the latest debian iso 5 | DOWNLOAD_LINK=$(grep -oP 'href="\K[^"]*debian-[0-9]+.[0-9]+.[0-9]+-amd64-netinst.iso' /tmp/debian-index.html) 6 | 7 | echo "Downloading the latest debian iso from: $DOWNLOAD_LINK" 8 | 9 | wget -O debian-original.iso $DOWNLOAD_LINK -------------------------------------------------------------------------------- /libre_workspace_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/libre_workspace_header.png -------------------------------------------------------------------------------- /linux-arbeitsplatz.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/linux-arbeitsplatz.deb -------------------------------------------------------------------------------- /preseed.cfg: -------------------------------------------------------------------------------- 1 | #_preseed_V1 2 | #### Contents of the preconfiguration file (for bullseye) 3 | 4 | # Language selection 5 | d-i debian-installer/language string de 6 | d-i debian-installer/country string DE 7 | d-i debian-installer/locale string de_DE.UTF-8 8 | 9 | # # Keyboard selection. 10 | #d-i keyboard-configuration/xkb-keymap select de 11 | # # d-i keyboard-configuration/toggle select No toggling 12 | 13 | ## Hostname setup and network configuration 14 | d-i netcfg/hostname string libre-workspace 15 | d-i netcfg/get_hostname unassigned-hostname 16 | d-i netcfg/get_domain unassigned-domain 17 | d-i netcfg/get_hostname seen true 18 | d-i netcfg/get_domain seen true 19 | 20 | ## Clock and time zone setup 21 | d-i clock-setup/utc boolean true 22 | d-i time/zone string Europe/Berlin 23 | 24 | 25 | ## Account setup: Empty password 26 | d-i passwd/root-password password 27 | d-i passwd/root-password-again password 28 | 29 | 30 | d-i passwd/user-fullname string SystemV 31 | d-i passwd/username string systemv 32 | # Normal user's password, either in clear text 33 | d-i passwd/user-password password LibreWorkspace 34 | d-i passwd/user-password-again password LibreWorkspace 35 | 36 | ## Partitioning: 37 | # Disable the following 7 lines to disable automatic partitioning by putting a '#' in front of it 38 | # d-i partman-auto/init_automatically_partition select biggest_free 39 | # d-i partman-auto/method string regular 40 | # d-i partman-auto/choose_recipe select atomic 41 | # d-i partman-partitioning/confirm_write_new_label boolean true 42 | # d-i partman/choose_partition select finish 43 | # d-i partman/confirm boolean true 44 | # d-i partman/confirm_nooverwrite boolean true 45 | 46 | ## Software: 47 | d-i apt-setup/non-free-firmware boolean true 48 | d-i apt-setup/non-free boolean true 49 | d-i apt-setup/contrib boolean true 50 | d-i apt-setup/disable-cdrom-entries boolean true 51 | 52 | ## Choose installation media 53 | d-i apt-setup/cdrom/set-first boolean false 54 | d-i apt-setup/cdrom/set-next boolean false 55 | d-i apt-setup/cdrom/set-failed boolean false 56 | 57 | ## Configure mirror-server (deb.debian.org) 58 | d-i mirror/country string de 59 | d-i mirror/http/hostname string deb.debian.org 60 | d-i mirror/http/directory string /debian 61 | d-i mirror/http/proxy string 62 | 63 | 64 | tasksel tasksel/first multiselect standard 65 | 66 | d-i pkgsel/include string vim openssh-server chromium chromium-l10n lightdm-autologin-greeter openbox 67 | 68 | popularity-contest popularity-contest/participate boolean true 69 | 70 | ## Grub 71 | d-i grub-installer/only_debian boolean true 72 | d-i grub-installer/with_other_os boolean true 73 | # d-i grub-installer/bootdev string default 74 | 75 | # Avoid that last message about the install being complete. 76 | d-i finish-install/reboot_in_progress note 77 | 78 | # Install custom package 79 | d-i partman/early_command string cp /cdrom/libre-workspace.deb /tmp/libre-workspace.deb 80 | d-i preseed/late_command string cp /tmp/libre-workspace.deb /target/ && in-target /usr/bin/apt install /libre-workspace.deb -y && in-target rm /libre-workspace.deb && in-target bash /usr/lib/libre-workspace/portal/prepare_for_first_boot.sh 81 | -------------------------------------------------------------------------------- /run_development.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # read cfg file: 4 | if [ -f "/etc/libre-workspace/portal/portal.conf" ]; then 5 | source /etc/libre-workspace/portal/portal.conf 6 | fi 7 | 8 | 9 | source /var/lib/libre-workspace/portal/venv/bin/activate 10 | 11 | pip install -r /usr/lib/libre-workspace/portal/requirements.txt 12 | 13 | 14 | if [ -d "/usr/lib/libre-workspace/portal" ]; then 15 | cd /usr/lib/libre-workspace/portal 16 | fi 17 | 18 | python manage.py makemigrations 19 | python3 manage.py migrate --no-input 20 | python3 manage.py collectstatic --no-input 21 | python manage.py creatersakey 22 | 23 | echo "Starting server..." 24 | python3 manage.py runserver localhost:8000 25 | -------------------------------------------------------------------------------- /splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/splash.png -------------------------------------------------------------------------------- /src/etc/libre-workspace/.gitignore: -------------------------------------------------------------------------------- 1 | libre-workspace.conf 2 | libre-workspace.env -------------------------------------------------------------------------------- /src/etc/libre-workspace/libre-workspace.env.example: -------------------------------------------------------------------------------- 1 | export IP="1.2.3.4" 2 | export ADMIN_PASSWORD="LibreWorkspace" 3 | export DOMAIN="int.de" 4 | export LDAP_DC="dc=int,dc=de" 5 | -------------------------------------------------------------------------------- /src/etc/libre-workspace/portal/.gitignore: -------------------------------------------------------------------------------- 1 | portal.conf -------------------------------------------------------------------------------- /src/etc/libre-workspace/portal/portal.conf.example: -------------------------------------------------------------------------------- 1 | # Here you can configure additional allowed hosts. Seperate the domains with a comma 2 | # export ALLOWED_HOSTS="custom.domain.com,custom2.domain.com" 3 | 4 | 5 | # Set this to True, if Libre Workspace should not run the welcome assistant. 6 | # For that especially Active Directory Server should be configured. 7 | # Enable the unix service if you skip the automated install: /usr/bin/systemctl enable libre-workspace-service.service 8 | export LINUX_ARBEITSPLATZ_CONFIGURED=False 9 | 10 | # Mail Settings 11 | # (This is only for the management interface, not for other services like nextcloud) 12 | export EMAIL_HOST="" 13 | export EMAIL_PORT="" 14 | export EMAIL_HOST_USER="" 15 | export EMAIL_HOST_EMAIL="" 16 | export EMAIL_HOST_PASSWORD="" 17 | 18 | # only activate (uncomment) one of these: 19 | export EMAIL_USE_TLS=True 20 | #export EMAIL_USE_SSL=True 21 | 22 | # This is ignored, if AUTH_LDAP_SERVER_URI is not blank 23 | # This is the initial "Administrator" password, if your instance uses no LDAP. 24 | export INITIAL_ADMIN_PASSWORD_WITHOUT_LDAP="LibreWorkspace" 25 | 26 | # Samba AD Settings 27 | # Change all instances of int and de to the real domain components 28 | # Example for AUTH_LDAP_SERVER_URI would be: "ldaps://la.int.de" 29 | # If you want to deactivate Samba AD integration, set AUTH_LDAP_SERVER_URI to "" 30 | export AUTH_LDAP_SERVER_URI="" 31 | export AUTH_LDAP_DC="dc=int,dc=de" 32 | export AUTH_LDAP_BIND_DN="cn=Administrator,cn=users,dc=int,dc=de" 33 | export AUTH_LDAP_BIND_PASSWORD="#####" 34 | export AUTH_LDAP_USER_DN_TEMPLATE="cn=%(user)s,cn=users,dc=int,dc=de" 35 | export AUTH_LDAP_GROUP_SEARCH_BASE="cn=Groups,dc=int,dc=de" 36 | export AUTH_LDAP_GROUP_ADMIN_DN="CN=Administrators,CN=Builtin,DC=int,DC=de" 37 | 38 | # Separate them with a , 39 | export HIDDEN_LDAP_USERS="dns-hostname" 40 | # Don't change the admin status for these nextcloud users automatically also if they are not in group "Domain Admin". Separate them with , 41 | # If set this value to "*" then the whole admin sync operation will be disabled. 42 | export IGNORE_ADMIN_STATUS_FOR_NEXTCLOUD_USERS="" 43 | 44 | export NEXTCLOUD_INSTALLATION_DIRECTORY="/var/www/nextcloud/" 45 | 46 | export M23_API_KEY="" 47 | -------------------------------------------------------------------------------- /src/join_scripts/linux-client/join_realm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Ensure that the dns server is set to the ip address of libre workspace (very important) 4 | 5 | # You can start this script with two arguments: 6 | # 1. The domain name of the realm. Example: int.de 7 | # 2. The client name for joining the realm. Example: client1 8 | 9 | # Get ip address of the server which will be used as dns server 10 | 11 | # Get the domain name 12 | # Is argument domain set? 13 | if [ -z "$1" ] ; then 14 | DOMAIN=$(zenity --entry --title="Domain" --text="Please enter the domain name of the realm. Example: int.de") 15 | else 16 | DOMAIN=$1 17 | fi 18 | export REALM=$(echo $DOMAIN | tr '[:lower:]' '[:upper:]') 19 | 20 | # Get the client name for joining the realm 21 | # Is argument client set? 22 | if [ -z "$2" ] ; then 23 | CLIENT=$(zenity --entry --title="Client" --text="Please enter the client name for joining the realm. Example: client1") 24 | else 25 | CLIENT=$2 26 | fi 27 | 28 | # Make sure time is synchronized 29 | apt install chrony -y 30 | chronyc makestep 31 | 32 | apt-get update -y 33 | apt-get install -y sssd-ad sssd-tools realmd adcli 34 | echo " 35 | [libdefaults] 36 | default_realm = $REALM 37 | dns_lookup_kdc = true # Or false if KDCs are manually listed 38 | dns_lookup_realm = false # Or true 39 | rdns = false 40 | 41 | [realms] 42 | $REALM = { 43 | kdc = la.$DOMAIN # Replace with your actual KDC hostname(s) or IP(s) 44 | admin_server = la.$DOMAIN # Often the same as a KDC 45 | } 46 | 47 | [domain_realm] 48 | .$DOMAIN = $REALM 49 | $DOMAIN = $REALM" > /etc/krb5.conf 50 | 51 | apt-get install -y krb5-user sssd-krb5 52 | 53 | hostnamectl set-hostname $CLIENT.$DOMAIN 54 | 55 | systemctl restart sssd 56 | echo "You need to enter the password of the realm administrator (libre workspace masterpassword):" 57 | kinit administrator 58 | 59 | # TODO: CHange IP to the IP of the client and adjust client name and also domain 60 | samba-tool dns add la.int.de int.de client1 A 192.168.1.192 -U administrator 61 | 62 | realm join -v -U administrator $DOMAIN 63 | 64 | # Add activate mkhomedir with pam-auth-update 65 | pam-auth-update --enable mkhomedir 66 | 67 | # Hide the user list 68 | echo " 69 | [Seat:*] 70 | greeter-show-manual-login=true 71 | #greeter-hide-users=true" >> /etc/lightdm/lightdm.conf 72 | 73 | echo "Please restart the system to apply the changes." -------------------------------------------------------------------------------- /src/usr/bin/libre-workspace-add-oidc-client: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if the script is run as root 4 | if [ "$(id -u)" -ne 0 ]; then 5 | echo "This script must be run as root" 1>&2 6 | exit 1 7 | fi 8 | 9 | . /etc/libre-workspace/portal/portal.conf 10 | 11 | # Activate the virtual environment 12 | if [ -f /var/lib/libre-workspace/portal/venv//bin/activate ]; then 13 | source /var/lib/libre-workspace/portal/venv//bin/activate 14 | fi 15 | 16 | # If the number of arguments is not equal to 4, then exit 17 | if [ "$#" -ne 4 ]; then 18 | echo "Illegal number of parameters" 19 | echo "Usage: $0 " 20 | exit 1 21 | fi 22 | 23 | # The response_types is set to ['1'] because the response type is 'code' 24 | CLEANED_DATA="""{ 25 | 'name': '$1', 26 | 'client_type': 'confidential', 27 | 'client_id': '$2', 28 | 'client_secret': '$3', 29 | 'response_types': ['1', '2', '3'], 30 | 'jwt_alg': 'RS256', 31 | 'redirect_uris': '$4', 32 | 'require_consent': False, 33 | 'reuse_consent': False, 34 | }""" 35 | 36 | echo $CLEANED_DATA 37 | 38 | python3 /usr/lib/libre-workspace/portal/manage.py shell -c "from idm.oidc_provider_settings import add_oidc_provider_client; add_oidc_provider_client($CLEANED_DATA);" 39 | 40 | if [ $? -eq 0 ]; then 41 | echo "OIDC provider client has been added" 42 | else 43 | echo "Failed to add OIDC provider client" 44 | exit 1 45 | fi -------------------------------------------------------------------------------- /src/usr/bin/libre-workspace-generate-secret: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | LENGTH=32 4 | 5 | # If $1 then set it to $LENGTH 6 | if [ -n "$1" ]; then 7 | LENGTH=$1 8 | fi 9 | 10 | # Generate a random string of a-zA-Z0-9 with length 11 | SECRET=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | head -c $LENGTH) 12 | 13 | echo $SECRET -------------------------------------------------------------------------------- /src/usr/bin/libre-workspace-portal: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if the script is run as root 4 | if [ "$(id -u)" -ne 0 ]; then 5 | echo "This script must be run as root" 1>&2 6 | exit 1 7 | fi 8 | 9 | # Check if the service is already running (by scanning the process list) 10 | if pgrep -f "gunicorn lac.wsgi:application --bind localhost:11123" > /dev/null; then 11 | echo "Service is already running" 12 | exit 0 13 | fi 14 | 15 | # Because of performance issues of key consitency check at oidc login we disable it 16 | # (https://github.com/juanifioren/django-oidc-provider/issues/374#issuecomment-1109039629) 17 | # Find a path to the file site-packages/Cryptodome/PublicKey/RSA.py 18 | cd /var/lib/libre-workspace/portal/venv 19 | FULL_PATH=$(find -name RSA.py 2>/dev/null | grep site-packages/Cryptodome/PublicKey/RSA.py) 20 | # If file exists replace the the line 21 | # return construct(der[1:6] + [Integer(der[4]).inverse(der[5])]) with 22 | # return construct(der[1:6] + [Integer(der[4]).inverse(der[5])], consistency_check=False) 23 | if [ -f "$FULL_PATH" ]; then 24 | sed -i 's/return construct(der\[1:6\] + \[Integer(der\[4\]).inverse(der\[5\])\])/return construct(der\[1:6\] + \[Integer(der\[4\]).inverse(der\[5\])\], consistency_check=False)/g' $FULL_PATH 25 | fi 26 | cd - 27 | 28 | # Make sure etc is only readable by owner: 29 | chmod 700 /etc/libre-workspace/ 30 | 31 | # read cfg file: 32 | if [ -f "/etc/libre-workspace/portal/portal.conf" ]; then 33 | source /etc/libre-workspace/portal/portal.conf 34 | fi 35 | 36 | source /var/lib/libre-workspace/portal/venv/bin/activate 37 | 38 | cd /usr/lib/libre-workspace/portal/ 39 | 40 | python3 manage.py migrate --no-input 41 | python3 manage.py collectstatic --no-input 42 | python manage.py creatersakey 43 | 44 | gunicorn lac.wsgi:application --bind localhost:11123 45 | 46 | -------------------------------------------------------------------------------- /src/usr/bin/libre-workspace-remove-oidc-client: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if the script is run as root 4 | if [ "$(id -u)" -ne 0 ]; then 5 | echo "This script must be run as root" 1>&2 6 | exit 1 7 | fi 8 | 9 | . /etc/libre-workspace/portal/portal.conf 10 | 11 | # Activate the virtual environment 12 | if [ -f /var/lib/libre-workspace/portal/venv/bin/activate ]; then 13 | source /var/lib/libre-workspace/portal/venv/bin/activate 14 | fi 15 | 16 | # If the number of arguments is not equal to 1, then exit 17 | if [ "$#" -ne 1 ]; then 18 | echo "Illegal number of parameters" 19 | echo "Usage: $0 " 20 | exit 1 21 | fi 22 | 23 | echo $CLEANED_DATA 24 | 25 | python3 /usr/lib/libre-workspace/portal/manage.py shell -c "from idm.oidc_provider_settings import remove_oidc_provider_client; remove_oidc_provider_client('$1');" -------------------------------------------------------------------------------- /src/usr/bin/libre-workspace-remove-webserver-entry: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # Needs one argument: hostname of the service 4 | # Removes a service entry from the Caddyfile e.g. "cloud.example.com" 5 | 6 | import sys 7 | import os 8 | 9 | # Get first argument which is the hostname of the service 10 | hostname = sys.argv[1] 11 | 12 | # Check if we are running as root 13 | if os.geteuid() != 0: 14 | print("This script must be run as root.") 15 | sys.exit(1) 16 | 17 | # Read Caddyfile 18 | with open("/etc/caddy/Caddyfile", "r") as f: 19 | lines = f.readlines() 20 | # Iterate over all lines in the Caddyfile looking for the hostname 21 | beginning_index = -1 22 | brackets_level = 0 23 | ending_index = -1 24 | for i in range(len(lines)): 25 | line = lines[i] 26 | if line.strip().startswith("#"): 27 | continue 28 | line = line.split("#")[0] 29 | line = line.strip() 30 | if line.startswith(f"{hostname}"): 31 | beginning_index = i 32 | print("Found beginning index", beginning_index) 33 | if beginning_index != -1: 34 | # Count { in the line 35 | brackets_level += line.count("{") 36 | # Count } in the line 37 | brackets_level -= line.count("}") 38 | 39 | if beginning_index != -1 and brackets_level == 0: 40 | # If the brackets level is 0, we found the end of the service entry 41 | ending_index = i 42 | print("Found ending index", ending_index) 43 | break 44 | 45 | # Remove all lines from the beginning index to the ending index 46 | if beginning_index != -1 and ending_index != -1: 47 | print(f"Removing service entry for {hostname} from Caddyfile") 48 | lines = lines[:beginning_index] + lines[ending_index+1:] 49 | 50 | # Write the new Caddyfile 51 | with open("/etc/caddy/Caddyfile", "w") as f: 52 | f.writelines(lines) 53 | print("Service entry removed from Caddyfile") 54 | 55 | os.system("systemctl restart caddy") 56 | sys.exit(0) 57 | -------------------------------------------------------------------------------- /src/usr/bin/libre-workspace-reset-2fa: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if the script is run as root 4 | if [ "$(id -u)" -ne 0 ]; then 5 | echo "This script must be run as root" 1>&2 6 | exit 1 7 | fi 8 | 9 | . /etc/libre-workspace/portal/portal.conf 10 | 11 | USERNAME="$1" 12 | if [ -z "$USERNAME" ]; then 13 | echo "Usage: $0 " 14 | exit 1 15 | fi 16 | 17 | if [ -d src/lac ]; then 18 | cd src/lac 19 | fi 20 | 21 | # Activate the virtual environment 22 | if [ -f /var/lib/libre-workspace/portal/venv/bin/activate ]; then 23 | source /var/lib/libre-workspace/portal/venv/bin/activate 24 | fi 25 | 26 | python3 manage.py shell -c "from idm.idm import reset_2fa_for_username; reset_2fa_for_username('$USERNAME')" 27 | 28 | if [ $? -ne 0 ]; then 29 | echo "Failed to reset 2FA for $USERNAME" 30 | exit 1 31 | fi 32 | 33 | # Notify the user 34 | echo "2FA for $USERNAME has been reset" -------------------------------------------------------------------------------- /src/usr/bin/libre-workspace-send-mail: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if the script is run as root 4 | if [ "$(id -u)" -ne 0 ]; then 5 | echo "This script must be run as root" 1>&2 6 | exit 1 7 | fi 8 | 9 | SUBJECT=$1 10 | MESSAGE=$2 11 | # Optional attachment: 12 | ATTACHEMENT_PATH=$3 13 | 14 | # Check if the first or second argument is empty 15 | if [ -z "$SUBJECT" ] || [ -z "$MESSAGE" ]; then 16 | echo "Usage: $0 [attachment_path]" 17 | exit 1 18 | fi 19 | # Check if the attachment path exists 20 | if [ -n "$ATTACHEMENT_PATH" ] && [ ! -f "$ATTACHEMENT_PATH" ]; then 21 | echo "WARNING: Attachment path does not exist: $ATTACHEMENT_PATH" 22 | fi 23 | 24 | . /var/lib/libre-workspace/local-admin-token 25 | 26 | # Check if ATTACHEMENT_PATH is set 27 | if [ -n "$ATTACHEMENT_PATH" ]; then 28 | # Send the email with the attachment 29 | curl -X POST -F "subject=$SUBJECT" -F "message=$MESSAGE" -F "attachment_path=$ATTACHEMENT_PATH" -F "lw_admin_token=$LW_ADMIN_TOKEN" localhost:11123/unix/send_mail 30 | else 31 | # Send the email without the attachment 32 | curl -X POST -F "subject=$SUBJECT" -F "message=$MESSAGE" -F "lw_admin_token=$LW_ADMIN_TOKEN" localhost:11123/unix/send_mail 33 | fi 34 | 35 | -------------------------------------------------------------------------------- /src/usr/bin/libre-workspace-service: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if the script is run as root 4 | if [ "$(id -u)" -ne 0 ]; then 5 | echo "This script must be run as root" 1>&2 6 | exit 1 7 | fi 8 | 9 | # check if etc/libre-workspace/portal/portal.conf exists 10 | if [ -f "/etc/libre-workspace/portal/portal.conf" ]; then 11 | source /etc/libre-workspace/portal/portal.conf 12 | else 13 | echo "Configuration file not found!" 14 | exit 1 15 | fi 16 | 17 | # Check if the service.py file exists 18 | if [ ! -f "/usr/lib/libre-workspace/portal/unix/unix_scripts/service.py" ]; then 19 | echo "Service file not found!" 20 | exit 1 21 | fi 22 | 23 | cd /usr/lib/libre-workspace/portal/unix/unix_scripts 24 | sudo python3 service.py 25 | -------------------------------------------------------------------------------- /src/usr/bin/libre-workspace-set-local-admin-password: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if the script is run as root 4 | if [ "$(id -u)" -ne 0 ]; then 5 | echo "This script must be run as root" 1>&2 6 | exit 1 7 | fi 8 | 9 | . /etc/libre-workspace/portal/portal.conf 10 | 11 | # Activate the virtual environment 12 | if [ -f /var/lib/libre-workspace/portal/venv/bin/activate ]; then 13 | source /var/lib/libre-workspace/portal/venv/bin/activate 14 | fi 15 | 16 | PASSWORD="$1" 17 | 18 | if [ -z "$PASSWORD" ]; then 19 | echo "Usage: $0 " 20 | exit 1 21 | fi 22 | 23 | # Set the password for the local Administrator user 24 | python3 manage.py shell -c "import idm.idm; idm.idm.change_superuser_password('$PASSWORD')" -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/collabora/caddy_collabora_entry.txt: -------------------------------------------------------------------------------- 1 | office.SED_DOMAIN { 2 | #tls internal 3 | encode gzip 4 | reverse_proxy https://127.0.0.1:9980 { 5 | transport http { 6 | tls_insecure_skip_verify 7 | } 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/collabora/remove_collabora.sh: -------------------------------------------------------------------------------- 1 | # Removes also all data! 2 | # Needs the following variables: 3 | # DOMAIN 4 | 5 | python3 ../remove_caddy_service.py office.$DOMAIN 6 | 7 | # If nextcloud is installed, remove the nextcloud office app 8 | if [ -d "/var/www/nextcloud" ]; then 9 | sudo -u www-data php /var/www/nextcloud/occ app:disable richdocuments 10 | fi 11 | 12 | # Remove the collabora container 13 | docker rm -f collabora 14 | 15 | # Remove the collabora installation directory 16 | rm -r /root/collabora -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/collabora/setup_collabora.sh: -------------------------------------------------------------------------------- 1 | # You need to run this script as root. 2 | # DOMAIN 3 | # ADMIN_PASSWORD 4 | # IP 5 | 6 | SCND_DOMAIN_LABEL=`echo $DOMAIN | cut -d'.' -f1` 7 | FRST_DOMAIN_LABEL=`echo $DOMAIN | cut -d'.' -f2` 8 | 9 | mkdir -p /root/collabora 10 | 11 | 12 | echo "docker pull collabora/code:latest 13 | docker run -t -d -p 9980:9980 -e "aliasgroup1=https://cloud\\\\.$SCND_DOMAIN_LABEL\\\\.$FRST_DOMAIN_LABEL:443" -e "username=admin" -e "password=beiSee8e" --restart unless-stopped --name collabora --add-host cloud.$DOMAIN:$IP collabora/code:latest" > /root/collabora/run.sh 14 | 15 | bash /root/collabora/run.sh 16 | docker exec collabora echo "$IP cloud.$DOMAIN" >> /etc/hosts 17 | 18 | # Add the content of caddy_collabora_entry.txt to /etc/caddy/Caddyfile 19 | cat caddy_collabora_entry.txt >> /etc/caddy/Caddyfile 20 | sed -i "s/SED_DOMAIN/$DOMAIN/g" /etc/caddy/Caddyfile 21 | 22 | 23 | # if $DOMAIN = "int.de" then uncomment #tls internal 24 | if [ $DOMAIN = "int.de" ] ; then 25 | sed -i "s/#tls internal/tls internal/g" /etc/caddy/Caddyfile 26 | fi 27 | 28 | systemctl restart caddy 29 | 30 | 31 | 32 | # Install in nextcloud the collabora app 33 | sudo -u www-data php /var/www/nextcloud/occ app:install richdocuments 34 | # We need this because if we removed it before and then reinstalled it, it is disabled: 35 | sudo -u www-data php /var/www/nextcloud/occ app:enable richdocuments 36 | 37 | # Configure onlyoffice 38 | sudo -u www-data php /var/www/nextcloud/occ config:app:set richdocuments wopi_url --value="https://office.$DOMAIN/" 39 | # if $DOMAIN = "int.de" then deactivate the certificate verification 40 | if [ $DOMAIN = "int.de" ] ; then 41 | sudo -u www-data php /var/www/nextcloud/occ config:app:set richdocuments disable_certificate_verification --value="yes" 42 | fi 43 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/collabora/update_collabora.sh: -------------------------------------------------------------------------------- 1 | cd /root/collabora 2 | 3 | docker rm -f collabora 4 | bash run.sh -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/desktop/administration/remove_user.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script removes a user from the linux-server. 4 | # We don't care about the guacamole database because it get's irrelevant after the user is removed. 5 | 6 | # This script should be run as root 7 | if [ "$EUID" -ne 0 ] 8 | then echo "Please run as root" 9 | exit 10 | fi 11 | 12 | # As variable we need the username 13 | USERNAME=$1 14 | 15 | deluser lw.$USERNAME 16 | rm -rf /home/lw.$USERNAME 17 | 18 | # Get the line number of the user in the sshd_config file 19 | LINE_NUMBER=$(grep -n "Match User lw.$USERNAME" /etc/ssh/sshd_config | cut -d: -f1) 20 | # Delete this line and the next line 21 | sed -i "$LINE_NUMBER,+1d" /etc/ssh/sshd_config 22 | 23 | systemctl restart sshd 24 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/desktop/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | guacamole: 3 | image: guacamole/guacamole:SED_GUACAMOLE_VERSION 4 | ports: 5 | - "28925:8080" 6 | links: 7 | - guacd 8 | - mysql 9 | environment: 10 | GUACD_HOSTNAME: guacd 11 | MYSQL_HOSTNAME: mysql 12 | MYSQL_PORT: 3306 13 | MYSQL_DATABASE: guacamole 14 | MYSQL_USER: guacamole 15 | MYSQL_PASSWORD: epho8Uk0 16 | MYSQL_ROOT_PASSWORD: Fei1woo9 17 | OPENID_AUTHORIZATION_ENDPOINT: SED_OPENID_AUTHORIZATION_ENDPOINT 18 | OPENID_JWKS_ENDPOINT: SED_OPENID_JWKS_ENDPOINT 19 | OPENID_ISSUER: SED_OPENID_ISSUER 20 | OPENID_CLIENT_ID: SED_OPENID_CLIENT_ID 21 | OPENID_REDIRECT_URI: SED_OPENID_REDIRECT_URI 22 | OPENID_USERNAME_CLAIM_TYPE: SED_OPENID_USERNAME_CLAIM_TYPE 23 | OPENID_GROUPS_CLAIM_TYPE: SED_OPENID_GROUPS_CLAIM_TYPE 24 | OPENID_MAX_TOKEN_VALIDITY: SED_OPENID_MAX_TOKEN_VALIDITY 25 | restart: unless-stopped 26 | extra_hosts: 27 | - "portal.int.de:SED_IP" 28 | 29 | guacd: 30 | image: guacamole/guacd 31 | restart: unless-stopped 32 | 33 | mysql: 34 | image: mariadb:latest 35 | environment: 36 | MYSQL_ROOT_PASSWORD: Fei1woo9 37 | MYSQL_DATABASE: guacamole 38 | MYSQL_USER: guacamole 39 | MYSQL_PASSWORD: epho8Uk0 40 | volumes: 41 | - mariadb_data:/var/lib/mysql 42 | - /root/desktop/initdb.sql:/docker-entrypoint-initdb.d/initdb.sql 43 | ports: 44 | - "3307:3306" 45 | restart: unless-stopped 46 | 47 | volumes: 48 | mariadb_data: -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/desktop/guacamole_version.sh: -------------------------------------------------------------------------------- 1 | export GUACAMOLE_VERSION="1.5.5" -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/desktop/remove_desktop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script should be run as root 4 | # We need this variables: 5 | # DOMAIN 6 | # IP 7 | # ADMIN_PASSWORD 8 | 9 | docker-compose -f /root/desktop/docker-compose.yml down --volumes 10 | 11 | 12 | DEBIAN_FRONTEND=noninteractive apt purge task-cinnamon-desktop xrdp -y 13 | DEBIAN_FRONTEND=noninteractive apt autoremove --purge -y 14 | 15 | rm -rf /root/desktop 16 | 17 | # Remove the entry from /etc/hosts 18 | sed -i "/desktop.$DOMAIN/d" /etc/hosts 19 | 20 | # Remove the DNS entry 21 | samba-tool dns delete la.$DOMAIN $DOMAIN desktop A $IP -Uadministrator%$ADMIN_PASSWORD 22 | 23 | # Remove the Caddy entry 24 | python3 ../remove_caddy_service.py desktop.$DOMAIN 25 | systemctl restart caddy 26 | 27 | ufw delete allow from 192.168.0.0/16 to any port 3389 28 | ufw delete allow from 172.16.0.0/12 to any port 3389 29 | 30 | # Remove all the users beginning with lw. 31 | USERS=$(ls /home | grep lw.) 32 | for USER in $USERS; do 33 | deluser $USER 34 | rm -rf /home/$USER 35 | done 36 | 37 | 38 | # Remove the OIDC client 39 | # TODO -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/desktop/scripts/auto_logout.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Time in seconds to wait before locking the screen (60 minutes) 4 | IDLE_TIME=3600 5 | 6 | # Function to lock the screen 7 | lock_screen() { 8 | echo "Locking the screen due to inactivity." 9 | # Replace the following line with your screen lock command 10 | cinnamon-session-quit --logout --no-prompt 11 | } 12 | 13 | # Get the initial mouse position 14 | initial_mouse_position=$(xdotool getmouselocation --shell | grep -E 'X|Y' | awk -F '=' '{print $2}') 15 | 16 | while true; do 17 | # Sleep for the idle time 18 | sleep $IDLE_TIME 19 | 20 | # Get the current mouse position 21 | current_mouse_position=$(xdotool getmouselocation --shell | grep -E 'X|Y' | awk -F '=' '{print $2}') 22 | 23 | # If the cinnamon session is not active anymore for $USER, then exit 24 | if ! pgrep -u $USER -x cinnamon > /dev/null; then 25 | exit 26 | fi 27 | 28 | # Check if the mouse position has changed 29 | if [ "$initial_mouse_position" == "$current_mouse_position" ]; then 30 | # Lock the screen 31 | lock_screen 32 | break 33 | else 34 | # Update the initial mouse position 35 | initial_mouse_position=$current_mouse_position 36 | fi 37 | done -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/desktop/scripts/setup_user_desktop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script is started if the user logs in. 4 | 5 | # Check if this script already ran 6 | if [ -f $HOME/.setup_desktop ]; then 7 | exit 8 | fi 9 | 10 | # Because otherwise the gsettings are not yet available 11 | sleep 10 12 | 13 | # We are in a cinnamon desktop environment 14 | 15 | # Set the background image 16 | gsettings set org.cinnamon.desktop.background picture-uri "file:///usr/lib/libre-workspace/portal/lac/static/lac/images/desktop_remote.jpg" 17 | 18 | # Set icon theme to yaru-blue 19 | gsettings set org.cinnamon.desktop.interface icon-theme "Yaru-blue" 20 | # Set cursor theme to yaru 21 | gsettings set org.cinnamon.desktop.interface cursor-theme "Yaru" 22 | # Set gtk theme to yaru 23 | gsettings set org.cinnamon.desktop.interface gtk-theme "Yaru-blue" 24 | # Set cinnamon theme to arc-dark 25 | gsettings set org.cinnamon.theme name "Arc-Dark" 26 | 27 | # Disable sound applet in the panel 28 | gsettings set org.cinnamon enabled-applets "['panel1:left:0:menu@cinnamon.org:0', 'panel1:left:1:separator@cinnamon.org:1', 'panel1:left:2:grouped-window-list@cinnamon.org:2', 'panel1:right:9:keyboard@cinnamon.org:8', 'panel1:right:10:favorites@cinnamon.org:9', 'panel1:right:13:power@cinnamon.org:12', 'panel1:right:14:calendar@cinnamon.org:13', 'panel1:right:15:cornerbar@cinnamon.org:14', 'panel1:right:3:xapp-status@cinnamon.org:15', 'panel1:right:2:notifications@cinnamon.org:16', 'panel1:right:1:systray@cinnamon.org:17', 'panel1:right:0:network@cinnamon.org:18']" 29 | 30 | # Remove terminal from the grouped window list 31 | # TODO 32 | 33 | # Disable logout prompt 34 | gsettings set org.cinnamon.SessionManager logout-prompt false 35 | # Enable auto-save-session 36 | gsettings set org.cinnamon.SessionManager auto-save-session true 37 | 38 | # Set bottom-notifications to true 39 | gsettings set org.cinnamon.desktop.notifications bottom-notifications true 40 | 41 | # Disable effects 42 | gsettings set org.cinnamon desktop-effects false 43 | gsettings set org.cinnamon desktop-effects-workspace false 44 | 45 | # Disable Shadows under windows 46 | if ! grep -q "export MUFFIN_NO_SHADOWS=1;" $HOME/.profile; then 47 | echo "export MUFFIN_NO_SHADOWS=1;" >> $HOME/.profile 48 | fi 49 | 50 | touch $HOME/.setup_desktop -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/desktop/update_desktop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script should be run as root 4 | # We need this variables: 5 | # DOMAIN 6 | # IP 7 | # ADMIN_PASSWORD 8 | 9 | # Not implemented yet, but guacamole is kind of timelessly working, so it is not that urgent. 10 | 11 | sudo apt update 12 | sudo apt upgrade -y -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/jitsi/caddy_jitsi_entry.txt: -------------------------------------------------------------------------------- 1 | meet.SED_DOMAIN { 2 | #tls internal 3 | reverse_proxy localhost:30323 4 | } 5 | 6 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/jitsi/remove_jitsi.sh: -------------------------------------------------------------------------------- 1 | # Removes also all data! 2 | # Needs the following variables: 3 | # DOMAIN 4 | 5 | python3 ../remove_caddy_service.py meet.$DOMAIN 6 | 7 | cd /root/jitsi 8 | docker-compose down --volumes 9 | cd - 10 | 11 | ufw delete allow 10000/udp 12 | rm -r ~/.jitsi-meet-cfg/ 13 | rm -r /root/jitsi 14 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/jitsi/setup_jitsi.sh: -------------------------------------------------------------------------------- 1 | # This script should be run as root 2 | # We need this variables: 3 | # DOMAIN 4 | # IP 5 | # ADMIN_PASSWORD 6 | 7 | # We need to update this link with the latest stable version regularly 8 | wget https://github.com/jitsi/docker-jitsi-meet/archive/refs/tags/stable-9078.zip 9 | unzip stable-9078.zip 10 | mv docker-jitsi-meet-stable-9078 /root/jitsi 11 | rm stable-9078.zip 12 | 13 | cp /root/jitsi/env.example /root/jitsi/.env 14 | 15 | # Change the HTTP_PORT to 30323 16 | sed -i "s/HTTP_PORT=8000/HTTP_PORT=30323/g" /root/jitsi/.env 17 | # Comment out HTTPS_PORT 18 | sed -i "s/HTTPS_PORT=8443/#HTTPS_PORT=443/g" /root/jitsi/.env 19 | # Set PUBLIC_URL to https://meet.$DOMAIN 20 | echo "PUBLIC_URL=https://meet.$DOMAIN" >> /root/jitsi/.env 21 | 22 | # Comment out - '${HTTPS_PORT}:443' 23 | sed -i "s/- '\${HTTPS_PORT}:443'/#/g" /root/jitsi/docker-compose.yml 24 | # Comment out - '127.0.0.1:${JVB_COLIBRI_PORT:-8080}:8080' 25 | sed -i "s/- '127.0.0.1:\${JVB_COLIBRI_PORT:-8080'/#/" /root/jitsi/docker-compose.yml 26 | 27 | cd /root/jitsi 28 | ./gen-passwords.sh 29 | mkdir -p ~/.jitsi-meet-cfg/{web,transcripts,prosody/config,prosody/prosody-plugins-custom,jicofo,jvb,jigasi,jibri} 30 | docker-compose up -d 31 | cd - 32 | 33 | ufw allow 10000/udp 34 | 35 | 36 | # Add the content of caddy_jitsi_entry.txt to /etc/caddy/Caddyfile 37 | cat caddy_jitsi_entry.txt >> /etc/caddy/Caddyfile 38 | sed -i "s/SED_DOMAIN/$DOMAIN/g" /etc/caddy/Caddyfile 39 | if [ $DOMAIN = "int.de" ] ; then 40 | sed -i "s/#tls internal/tls internal/g" /etc/caddy/Caddyfile 41 | fi 42 | systemctl restart caddy 43 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/jitsi/update_jitsi.sh: -------------------------------------------------------------------------------- 1 | cd /root/jitsi 2 | 3 | # Ensure that in the .env file the variable "JITSI_IMAGE_VERSION" is set to "stable" 4 | # Delete the line with "JITSI_IMAGE_VERSION=latest" 5 | sed -i "/JITSI_IMAGE_VERSION/d" .env 6 | # Add the line "JITSI_IMAGE_VERSION=stable" 7 | echo "JITSI_IMAGE_VERSION=stable" >> .env 8 | 9 | # Update Jitsi 10 | docker-compose down # To avoid problems with the containers after the update 11 | docker-compose pull 12 | docker-compose up -d 13 | 14 | 15 | # docker compose compatibility: 16 | docker compose pull 17 | # Because sometimes docker has problems by itself, we need to remove the containers and start them again 18 | docker compose down 19 | docker compose up -d -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/matrix/docker_matrix_entry.txt: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | 3 | services: 4 | db: 5 | image: postgres:13 6 | restart: unless-stopped 7 | environment: 8 | - POSTGRES_USER=synapse 9 | - POSTGRES_PASSWORD=OoRei7oh 10 | - POSTGRES_DB=synapse 11 | - POSTGRES_INITDB_ARGS=--encoding='UTF8' --lc-collate='C' --lc-ctype='C' 12 | volumes: 13 | - ./postgres-data:/var/lib/postgresql/data 14 | synapse: 15 | image: matrixdotorg/synapse:latest 16 | restart: unless-stopped 17 | volumes: 18 | - ./synapse-data:/data 19 | ports: 20 | - 8008:8008 21 | depends_on: 22 | - db 23 | element: 24 | container_name: element 25 | image: vectorim/element-web 26 | restart: unless-stopped 27 | ports: 28 | - 15124:80 29 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/matrix/remove_matrix.sh: -------------------------------------------------------------------------------- 1 | # Removes also all data! 2 | # Needs the following variables: 3 | # DOMAIN 4 | 5 | python3 ../remove_caddy_service.py element.$DOMAIN 6 | python3 ../remove_caddy_service.py matrix.$DOMAIN 7 | 8 | cd /root/matrix 9 | docker-compose down --volumes 10 | cd - 11 | 12 | rm -r /root/matrix 13 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/matrix/update_element_config.sh: -------------------------------------------------------------------------------- 1 | # Needs the environment variable DOMAIN e.g.: int.de 2 | 3 | # Write new element config 4 | # Change element app/config.json inside the docker container 5 | echo "Updating element config..." 6 | docker cp element:/app/config.json /root/matrix/ 7 | sed -i "s#https://matrix-client.matrix.org#https://matrix.$DOMAIN#g" /root/matrix/config.json 8 | sed -i "s#https://matrix.org#https://matrix.$DOMAIN#g" /root/matrix/config.json 9 | sed -i "s#matrix.org#matrix.$DOMAIN#g" /root/matrix/config.json 10 | sed -i "s#meet.element.io#meet.$DOMAIN#g" /root/matrix/config.json 11 | 12 | # Copy the changed config.json back to the docker container 13 | docker cp /root/matrix/config.json element:/app/ 14 | rm /root/matrix/config.json 15 | 16 | # Fixing bug: https://github.com/element-hq/element-web/issues/29371 17 | docker cp element:/docker-entrypoint.d/18-load-element-modules.sh /tmp/ 18 | # Replace the line mkdir /tmp/element-web-config with mkdir -p /tmp/element-web-config 19 | sed -i "s#mkdir /tmp/element-web-config#mkdir -p /tmp/element-web-config#g" /tmp/18-load-element-modules.sh 20 | docker cp /tmp/18-load-element-modules.sh element:/docker-entrypoint.d/ 21 | rm /tmp/18-load-element-modules.sh 22 | 23 | # Restart the element container 24 | docker restart element 25 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/matrix/update_env.sh: -------------------------------------------------------------------------------- 1 | # This script should be run as root 2 | # We need these variables: 3 | # DOMAIN (this doesn't change) 4 | # IP 5 | # ADMIN_PASSWORD 6 | 7 | # Change password of the ldap Administrator user in /root/matrix/synapse-data/homeserver.yaml 8 | sed -i "s/bind_password:.*/bind_password: \"$ADMIN_PASSWORD\"/g" /root/matrix/synapse-data/homeserver.yaml 9 | 10 | # Change uri in /root/matrix/synapse-data/homeserver.yaml 11 | sed -i "s/uri:.*/uri: \"ldaps:\/\/$IP:636\"/g" /root/matrix/synapse-data/homeserver.yaml -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/matrix/update_matrix.sh: -------------------------------------------------------------------------------- 1 | # Update Matrix 2 | docker-compose -f /root/matrix/docker-compose.yml pull 3 | # Matrix Setup sometimes has problems with the network, so we need to remove the containers and start them again 4 | docker-compose -f /root/matrix/docker-compose.yml down 5 | docker-compose -f /root/matrix/docker-compose.yml up -d 6 | 7 | # docker compose compatibility: 8 | docker compose -f /root/matrix/docker-compose.yml pull 9 | # Because sometimes docker has problems by itself, we need to remove the containers and start them again 10 | docker compose -f /root/matrix/docker-compose.yml down 11 | docker compose -f /root/matrix/docker-compose.yml up -d 12 | 13 | . /etc/libre-workspace/libre-workspace.env 14 | . /usr/lib/libre-workspace/modules/matrix/update_element_config.sh 15 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/nextcloud/caddy_nextcloud_entry.txt: -------------------------------------------------------------------------------- 1 | cloud.SED_DOMAIN { 2 | #tls internal 3 | 4 | @lw_usersettings { 5 | path /settings/users 6 | path /index.php/settings/users 7 | } 8 | handle @lw_usersettings { 9 | redir https://portal.SED_DOMAIN/idm/user_overview 10 | } 11 | 12 | root * /var/www/nextcloud 13 | file_server 14 | 15 | php_fastcgi unix//var/run/php/php-fpm.sock { 16 | # This is for removing "index.php" from the URL 17 | env front_controller_active true 18 | } 19 | 20 | header { 21 | Strict-Transport-Security max-age=31536000; # enable HSTS 22 | } 23 | 24 | redir /.well-known/carddav /remote.php/dav 301 25 | redir /.well-known/caldav /remote.php/dav 301 26 | 27 | @forbidden { 28 | path /.htaccess 29 | path /data/* 30 | path /config/* 31 | path /db_structure 32 | path /.xml 33 | path /README 34 | path /3rdparty/* 35 | path /lib/* 36 | path /templates/* 37 | path /occ 38 | path /console.php 39 | } 40 | 41 | respond @forbidden 404 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/nextcloud/patches/2024-06-25_install_pdo_sqlite.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get the current file name 4 | FILE_NAME=$(basename $0) 5 | # Get the date of the filename which is like this: 2024-06-25 6 | DATE=${FILE_NAME:0:10} 7 | # Check if the file is older than 365 days 8 | if [ $(( ($(date +%s) - $(date -d $DATE +%s)) / 86400 )) -gt 365 ]; then 9 | echo "Patch is older than 365 days. Exiting patch." 10 | exit 0 11 | fi 12 | 13 | apt-get install php-pgsql php-sqlite3 -y 14 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/nextcloud/patches/2024-06-25_move_to_apt_redis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get the current file name 4 | FILE_NAME=$(basename $0) 5 | # Get the date of the filename which is like this: 2024-06-25 6 | DATE=${FILE_NAME:0:10} 7 | # Check if the file is older than 365 days 8 | if [ $(( ($(date +%s) - $(date -d $DATE +%s)) / 86400 )) -gt 365 ]; then 9 | echo "Patch is older than 365 days. Exiting patch." 10 | exit 0 11 | fi 12 | 13 | # Check if we need to apply the patch 14 | # Is redis installed? 15 | if [ -x "$(command -v redis-server)" ]; then 16 | echo "Redis is already installed. Exiting patch." 17 | exit 0 18 | fi 19 | 20 | # Install redis and php packages 21 | apt-get install redis php-redis php-apcu php-memcache pwgen -y 22 | 23 | # Set redis password 24 | REDIS_PASSWORD=$(pwgen -n 20 1) 25 | echo "" >> /etc/redis/redis.conf 26 | echo "requirepass $REDIS_PASSWORD" >> /etc/redis/redis.conf 27 | 28 | # Enable redis and restart it 29 | systemctl enable redis-server 30 | systemctl restart redis-server 31 | 32 | # Configure nextcloud to use redis 33 | # Disable all caches that nextcloud doesn't fail while we are changing the cache settings 34 | sudo -u www-data php /var/www/nextcloud/occ config:system:delete memcache.local 35 | sudo -u www-data php /var/www/nextcloud/occ config:system:delete memcache.distributed 36 | sudo -u www-data php /var/www/nextcloud/occ config:system:delete memcache.locking 37 | 38 | sudo -u www-data php /var/www/nextcloud/occ config:system:set redis host --value localhost 39 | sudo -u www-data php /var/www/nextcloud/occ config:system:set redis port --value 6379 40 | sudo -u www-data php /var/www/nextcloud/occ config:system:set redis dbindex --value 0 41 | sudo -u www-data php /var/www/nextcloud/occ config:system:set redis password --value "$REDIS_PASSWORD" 42 | sudo -u www-data php /var/www/nextcloud/occ config:system:set memcache.locking --value '\OC\Memcache\Redis' 43 | sudo -u www-data php /var/www/nextcloud/occ config:system:set memcache.distributed --value '\OC\Memcache\Redis' 44 | # We set the local cache to APCu, because it is faster than redis for local cache 45 | sudo -u www-data php /var/www/nextcloud/occ config:system:set memcache.local --value '\OC\Memcache\APCu' 46 | 47 | # Restart php 48 | systemctl restart php* 49 | 50 | # If /root/redis-nextcloud/docker-compose.yml exists, then remove it 51 | if [ -f /root/redis-nextcloud/docker-compose.yml ]; then 52 | docker-compose -f /root/redis-nextcloud/docker-compose.yml down --volumes 53 | rm -rf /root/redis-nextcloud 54 | fi -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/nextcloud/patches/2024-08-01_fix_localhost_trusted_domains.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get the current file name 4 | FILE_NAME=$(basename $0) 5 | # Get the date of the filename which is like this: 2024-06-25 6 | DATE=${FILE_NAME:0:10} 7 | 8 | # Check if the file is older than 365 days 9 | if [ $(( ($(date +%s) - $(date -d $DATE +%s)) / 86400 )) -gt 365 ]; then 10 | echo "Patch is older than 365 days. Exiting patch." 11 | exit 0 12 | fi 13 | 14 | # Check if we need to apply the patch 15 | # Is localhost not in the trusted domains? Then we need to exit the patch 16 | if ! sudo -u www-data php /var/www/nextcloud/occ config:system:get trusted_domains | grep -q localhost; then 17 | if ! sudo -u www-data php /var/www/nextcloud/occ config:system:get overwrite.cli.url | grep -q localhost; then 18 | echo "Localhost is not in the trusted domains and not in overwrite.cli.url Everything okay. Exiting patch." 19 | exit 0 20 | fi 21 | fi 22 | 23 | sudo -u www-data php /var/www/nextcloud/occ config:system:delete trusted_domains 0 24 | sudo -u www-data php /var/www/nextcloud/occ config:system:set trusted_domains 0 --value cloud.$DOMAIN 25 | sudo -u www-data php /var/www/nextcloud/occ config:system:set overwrite.cli.url --value https://cloud.$DOMAIN -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/nextcloud/remove_nextcloud.sh: -------------------------------------------------------------------------------- 1 | # Removes also all data! 2 | # Needs the following variables: 3 | # DOMAIN 4 | 5 | python3 ../remove_caddy_service.py cloud.$DOMAIN 6 | 7 | if [ -d "/data/nextcloud" ]; then 8 | rm -r /data/nextcloud 9 | fi 10 | 11 | # Drop the nextcloud database 12 | mysql -u root -p -e "DROP DATABASE nextcloud;" 13 | 14 | # Remove the cronjob 15 | crontab -u www-data -l | grep -v "/var/www/nextcloud/cron.php" | crontab -u www-data - 16 | 17 | # Remove the nextcloud installation directory 18 | rm -r /var/www/nextcloud -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/nextcloud/update_env.sh: -------------------------------------------------------------------------------- 1 | # This script should be run as root 2 | # We need these variables: 3 | # DOMAIN (this doesn't change) 4 | # IP 5 | # ADMIN_PASSWORD 6 | 7 | # Change password of the nextcloud Administrator user 8 | export OC_PASS=$ADMIN_PASSWORD 9 | sudo -u www-data php /var/www/nextcloud/occ user:resetpassword --password-from-env Administrator 10 | 11 | # Change password of the ldap Administrator user 12 | sudo -u www-data php /var/www/nextcloud/occ ldap:set-config s01 ldapAgentPassword "$ADMIN_PASSWORD" 13 | 14 | # Update trusted proxies 15 | sudo -u www-data php /var/www/nextcloud/occ config:system:set trusted_proxies 0 --value=$IP -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/nextcloud/update_nextcloud.sh: -------------------------------------------------------------------------------- 1 | sudo -u www-data php /var/www/nextcloud/updater/updater.phar --no-interaction 2 | sudo -u www-data php /var/www/nextcloud/occ upgrade 3 | 4 | # Update the database 5 | sudo -u www-data php /var/www/nextcloud/occ db:add-missing-indices 6 | 7 | # Repair nextcloud (sometimes this is needed by nextcloud itself.) 8 | sudo -u www-data php /var/www/nextcloud/occ maintenance:repair --include-expensive -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/onlyoffice/caddy_onlyoffice_entry.txt: -------------------------------------------------------------------------------- 1 | office.SED_DOMAIN { 2 | #tls internal 3 | header { 4 | X-Forwarded-Proto: https; 5 | access-control-allow-origin: *; 6 | } 7 | reverse_proxy http://localhost:10923 8 | } 9 | 10 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/onlyoffice/remove_onlyoffice.sh: -------------------------------------------------------------------------------- 1 | # Removes also all data! 2 | # Needs the following variables: 3 | # DOMAIN 4 | 5 | libre-workspace-remove-webserver-entry office.$DOMAIN 6 | 7 | # If nextcloud is installed, remove the onlyoffice app 8 | if [ -d "/var/www/nextcloud" ]; then 9 | sudo -u www-data php /var/www/nextcloud/occ app:disable onlyoffice 10 | sudo -u www-data php /var/www/nextcloud/occ app:remove onlyoffice 11 | fi 12 | 13 | # Remove the onlyoffice container 14 | docker rm -f onlyoffice 15 | 16 | # Remove the onlyoffice installation directory 17 | rm -r /root/onlyoffice -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/onlyoffice/setup_onlyoffice.sh: -------------------------------------------------------------------------------- 1 | # You need to run this script as root. 2 | # DOMAIN 3 | # ADMIN_PASSWORD 4 | # IP 5 | 6 | mkdir -p /root/onlyoffice 7 | 8 | 9 | echo "docker pull onlyoffice/documentserver:latest 10 | docker run -i -t -d -p 10923:80 --restart=unless-stopped --name onlyoffice -e JWT_ENABLED='true' -e JWT_SECRET='$ADMIN_PASSWORD' --add-host \"cloud.$DOMAIN:$IP\" onlyoffice/documentserver:latest" > /root/onlyoffice/run.sh 11 | 12 | 13 | if [ "$DOMAIN" = "int.de" ] ; then 14 | echo " 15 | docker exec onlyoffice sed -i 's/\"rejectUnauthorized\": true/\"rejectUnauthorized\": false/g' /etc/onlyoffice/documentserver/default.json 16 | docker restart onlyoffice 17 | " >> /root/onlyoffice/run.sh 18 | fi 19 | 20 | bash /root/onlyoffice/run.sh 21 | 22 | # Add the content of caddy_onlyoffice_entry.txt to /etc/caddy/Caddyfile 23 | cat caddy_onlyoffice_entry.txt >> /etc/caddy/Caddyfile 24 | sed -i "s/SED_DOMAIN/$DOMAIN/g" /etc/caddy/Caddyfile 25 | 26 | 27 | # if $DOMAIN = "int.de" then uncomment #tls internal 28 | if [ "$DOMAIN" = "int.de" ] ; then 29 | sed -i "s/#tls internal/tls internal/g" /etc/caddy/Caddyfile 30 | fi 31 | 32 | systemctl restart caddy 33 | 34 | 35 | 36 | # Install in nextcloud the onlyoffice app 37 | sudo -u www-data php /var/www/nextcloud/occ app:install onlyoffice 38 | # We need this because if we removed it before and then reinstalled it, it is disabled: 39 | sudo -u www-data php /var/www/nextcloud/occ app:enable onlyoffice 40 | 41 | # Configure onlyoffice 42 | sudo -u www-data php /var/www/nextcloud/occ config:app:set onlyoffice DocumentServerUrl --value="https://office.$DOMAIN/" 43 | # Set the secret ($ADMIN_PASSWORD) 44 | sudo -u www-data php /var/www/nextcloud/occ config:app:set onlyoffice jwt_secret --value="$ADMIN_PASSWORD" 45 | # if $DOMAIN = "int.de" then deactivate the certificate verification 46 | if [ "$DOMAIN" = "int.de" ] ; then 47 | sudo -u www-data php /var/www/nextcloud/occ config:app:set onlyoffice verify_peer_off --value="true" 48 | fi 49 | # Disable the document preview 50 | sudo -u www-data php /var/www/nextcloud/occ config:app:set onlyoffice preview --value="false" 51 | 52 | # Set the check interval to 0 to prevent disabling the app itself 53 | sudo -u www-data php /var/www/nextcloud/occ config:app:set onlyoffice editors_check_interval --value='0' -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/onlyoffice/update_env.sh: -------------------------------------------------------------------------------- 1 | # This script should be run as root 2 | # We need these variables: 3 | # DOMAIN (this doesn't change) 4 | # IP 5 | # ADMIN_PASSWORD 6 | 7 | echo "docker pull onlyoffice/documentserver:latest 8 | docker run -i -t -d -p 10923:80 --restart=unless-stopped --name onlyoffice -e JWT_ENABLED='true' -e JWT_SECRET='$ADMIN_PASSWORD' onlyoffice/documentserver:latest --add-host cloud.$DOMAIN:$IP" > /root/onlyoffice/run.sh 9 | 10 | docker rm -f onlyoffice 11 | bash /root/onlyoffice/run.sh -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/onlyoffice/update_onlyoffice.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | cd /root/onlyoffice 5 | 6 | docker rm -f onlyoffice 7 | bash run.sh 8 | 9 | # Update onlyoffice app inside nextcloud 10 | sudo -u www-data php /var/www/nextcloud/occ app:update onlyoffice 11 | 12 | # Set the settings_error to "" to prevent onlyoffice from disabling itself 13 | sudo -u www-data php /var/www/nextcloud/occ config:app:set onlyoffice settings_error --value "" -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/samba_dc/patches/2024-12-14_mark_samba_dc_installed.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get the current file name 4 | FILE_NAME=$(basename $0) 5 | # Get the date of the filename which is like this: 2024-06-25 6 | DATE=${FILE_NAME:0:10} 7 | # Check if the file is older than 365 days 8 | if [ $(( ($(date +%s) - $(date -d $DATE +%s)) / 86400 )) -gt 365 ]; then 9 | echo "Patch is older than 365 days. Exiting patch." 10 | exit 0 11 | fi 12 | 13 | # Check if we need to apply the patch 14 | # Is samba installed and not /root/samba_dc exists? 15 | if [ -x "$(command -v samba-tool)" ] && [ -f /root/samba_dc ]; then 16 | echo "Samba is already installed and marked. Exiting patch." 17 | exit 0 18 | fi 19 | 20 | # Mark samba_dc installed if samba-tool is installed 21 | if [ -x "$(command -v samba-tool)" ]; then 22 | ln -s /etc/samba /root/samba_dc 23 | fi -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/samba_dc/remove_samba_dc.sh: -------------------------------------------------------------------------------- 1 | # This script should be run as root 2 | # We need this variables: 3 | # DOMAIN 4 | # IP 5 | # ADMIN_PASSWORD 6 | # LDAP_DC 7 | 8 | # Remove samba dc 9 | apt purge -y acl attr samba samba-dsdb-modules samba-vfs-modules smbclient winbind libpam-winbind libnss-winbind libpam-krb5 krb5-config krb5-user dnsutils chrony net-tools samba-ad-provision 10 | sudo apt autoremove --purge -y 11 | 12 | # Install dnsmasq as replacement for samba dns server 13 | apt install -y dnsmasq 14 | echo " 15 | listen-address=$IP" >> /etc/dnsmasq.conf 16 | systemctl enable --now dnsmasq 17 | systemctl restart dnsmasq 18 | 19 | # Update cfg file: 20 | # Remove the lines with "AUTH_LDAP" in it 21 | sed -i "/AUTH_LDAP/d" /etc/libre-workspace/portal/portal.conf 22 | sed -i "/INITIAL_ADMIN_PASSWORD_WITHOUT_LDAP/d" /etc/libre-workspace/portal/portal.conf 23 | # Add the Samba AD disabled flag to the cfg file 24 | # Ensure that we put in a new line 25 | echo "" >> /etc/libre-workspace/portal/portal.conf 26 | echo "export AUTH_LDAP_SERVER_URI=\"\" 27 | export INITIAL_ADMIN_PASSWORD_WITHOUT_LDAP=\"$ADMIN_PASSWORD\"" >>/etc/libre-workspace/portal/portal.conf 28 | 29 | 30 | # Remove the /root/samba_dc symbolic link 31 | rm /root/samba_dc 32 | # Remove the /etc/samba directory 33 | rm -rf /etc/samba 34 | 35 | # Reset the local Administrator by setting the password to $ADMIN_PASSWORD 36 | libre-workspace-set-local-admin-password "$ADMIN_PASSWORD" 37 | libre-workspace-reset-2fa 38 | 39 | # Restart Libre Worksapce Services 40 | systemctl restart libre-workspace-service.service 41 | systemctl restart libre-workspace-portal.service -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/samba_dc/update_samba_dc.sh: -------------------------------------------------------------------------------- 1 | # This script should be run as root 2 | # We need this variables: 3 | # DOMAIN 4 | # IP 5 | # ADMIN_PASSWORD 6 | # LDAP_DC 7 | 8 | apt update 9 | apt install -y acl attr samba samba-dsdb-modules samba-vfs-modules smbclient winbind libpam-winbind libnss-winbind libpam-krb5 krb5-config krb5-user dnsutils chrony net-tools samba-ad-provision 10 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/xfce/remove_xfce.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | apt-get purge task-xfce-desktop lightdm-gtk-greeter -y 4 | apt-get install lightdm-autologin-greeter openbox -y 5 | 6 | /sbin/reboot 7 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/xfce/setup_xfce.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | apt-get purge lightdm-autologin-greeter openbox -y 4 | apt-get install lightdm-gtk-greeter -y 5 | apt-get install task-xfce-desktop -y 6 | apt-get install gvfs-backends seahorse gdebi -y 7 | 8 | # Enable userlist for lightdm 9 | sed -i "s/^#greeter-hide-users=.*/greeter-hide-users=false/" "/etc/lightdm/lightdm.conf" 10 | 11 | # Set desktop background 12 | rm /usr/share/images/desktop-base/default 13 | ln -s /usr/lib/libre-workspace/portal/lac/static/lac/images/desktop.jpg /usr/share/images/desktop-base/default -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/xfce/update_env.sh: -------------------------------------------------------------------------------- 1 | # We don't have to do anything here. -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/modules/xfce/update_xfce.sh: -------------------------------------------------------------------------------- 1 | # We don't have to do anything here, 2 | # because the desktop gets updated by the normal update process of system packages. -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/addon_creator/__init__.py -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/addon_template/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright {{addon.year}} {{addon.mail}} 3 | Scripts licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/addon_template/addon.conf: -------------------------------------------------------------------------------- 1 | id="{{addon.id}}" 2 | name="{{addon.name}}" 3 | description="{{addon.description}}" 4 | author="{{addon.author}}" 5 | email="{{addon.mail}}" 6 | url="{{addon.url}}" -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/addon_template/control: -------------------------------------------------------------------------------- 1 | Package: libre-workspace-module-{{addon.id}} 2 | Version: 0.1.0 3 | Depends: libre-workspace-portal 4 | Maintainer: {{addon.author}} 5 | Architecture: all 6 | Homepage: {{addon.project_homepage}} 7 | Section: admin 8 | Installed-Size: 0 9 | Description: Libre Workspace Module {{addon.id}} 10 | 11 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/addon_template/install: -------------------------------------------------------------------------------- 1 | usr 2 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/addon_template/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if module already is installed (is /root/addon.id directory present?) 4 | if [ -d "/root/{{addon.id}}" ]; then 5 | echo "Module {{addon.id}} is already installed." 6 | exit 0 7 | fi 8 | 9 | echo "Installing module {{addon.id}}..." 10 | 11 | mkdir -p /root/{{addon.id}} 12 | 13 | . /etc/libre-workspace/libre-workspace.env 14 | 15 | cd /usr/lib/libre-workspace/modules/{{addon.id}} 16 | 17 | . setup_{{addon.id}}.sh -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/addon_template/remove_addon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script gets these variables passed: $DOMAIN, $ADMIN_PASSWORD, $IP, $LDAP_DC 3 | 4 | docker-compose -f /root/{{addon.id}}/docker-compose.yml down --volumes 5 | rm -rf /root/{{addon.id}} 6 | # Remove the entry from the Caddyfile 7 | libre-workspace-remove-webserver-entry {{addon.url}}.$DOMAIN 8 | systemctl restart caddy -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/addon_template/setup_addon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script gets these variables passed: $DOMAIN, $ADMIN_PASSWORD, $IP, $LDAP_DC 3 | mkdir -p /root/{{addon.id}} 4 | # Dont forget to escape " with a backslash: 5 | cp docker-compose.yml /root/{{addon.id}}/docker-compose.yml 6 | 7 | # Envsubst is used to replace variables in the docker-compose.yml file 8 | export DOMAIN=$DOMAIN 9 | export ADMIN_PASSWORD=$ADMIN_PASSWORD 10 | export IP=$IP 11 | export LDAP_DC=$LDAP_DC 12 | envsubst < docker-compose.yml > /root/{{addon.id}}/docker-compose.yml 13 | 14 | docker-compose -f /root/{{addon.id}}/docker-compose.yml up -d 15 | 16 | echo "{{addon.url}}.$DOMAIN { 17 | #tls internal 18 | reverse_proxy localhost:{{addon.internal_port}} 19 | } 20 | 21 | " >> /etc/caddy/Caddyfile 22 | 23 | # If domain is "int.de" uncomment the tls internal line for internal https 24 | if [ "$DOMAIN" = "int.de" ]; then 25 | sed -i 's/#tls internal/tls internal/g' /etc/caddy/Caddyfile 26 | fi 27 | 28 | systemctl restart caddy -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/addon_template/update_addon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script gets these variables passed: $DOMAIN, $ADMIN_PASSWORD, $IP, $LDAP_DC 3 | 4 | docker-compose -f /root/{{addon.id}}/docker-compose.yml pull 5 | docker-compose -f /root/{{addon.id}}/docker-compose.yml up -d -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AddonCreatorConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'addon_creator' 7 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.utils.safestring import mark_safe 3 | 4 | 5 | class AddonCreatorForm(forms.Form): 6 | addon_id = forms.CharField( 7 | label="Addon ID (klein und zusammen geschrieben)", 8 | max_length=100, 9 | required=True, 10 | widget=forms.TextInput(attrs={"placeholder": "nocodb"}) 11 | ) 12 | addon_name = forms.CharField( 13 | label="Addon Name", 14 | max_length=100, 15 | required=True, 16 | widget=forms.TextInput(attrs={"placeholder": "Noco DB"}) 17 | ) 18 | addon_description = forms.CharField( 19 | label="Addon Beschreibung (max. 10 Wörter)", 20 | max_length=100, 21 | required=True, 22 | widget=forms.TextInput(attrs={"placeholder": "Datenbank-Verwaltung"}) 23 | ) 24 | project_homepage = forms.CharField( 25 | label="Projekt Webseite (optional)", 26 | max_length=200, 27 | required=False, 28 | widget=forms.TextInput(attrs={"placeholder": "https://www.nocodb.com"}) 29 | ) 30 | addon_author = forms.CharField( 31 | label="Addon Autor", 32 | max_length=100, 33 | required=True, 34 | widget=forms.TextInput(attrs={"placeholder": "Mein Name"}) 35 | ) 36 | addon_author_email = forms.EmailField( 37 | label="Addon Autor E-Mail", 38 | max_length=100, 39 | required=True, 40 | widget=forms.TextInput(attrs={"placeholder": "mail@example.com"}) 41 | ) 42 | addon_url = forms.CharField( 43 | label="Addon URL (Empfohlen: ähnlich/gleich zur Addon ID)", 44 | max_length=100, 45 | required=True, 46 | widget=forms.TextInput(attrs={"placeholder": "db"}) 47 | ) 48 | addon_docker_compose = forms.CharField( 49 | label="docker-compose.yml Inhalt", 50 | widget=forms.Textarea 51 | ) 52 | addon_internal_port = forms.IntegerField( 53 | label="Interner http-Port für den Webserver (>1000)", 54 | min_value=1000, 55 | max_value=65535, 56 | required=True 57 | ) 58 | addon_logo = forms.ImageField( 59 | label="Addon-Logo (Empfohlen: 256x256px webp)", 60 | required=False 61 | ) 62 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/addon_creator/migrations/__init__.py -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | urlpatterns = [ 6 | path("", views.addon_creator, name="addon_creator"), 7 | ] -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/addon_creator/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.urls import reverse 3 | from .forms import AddonCreatorForm 4 | from .utils import create_addon 5 | from django.http import HttpResponse 6 | from django.contrib.admin.views.decorators import staff_member_required 7 | from django.conf import settings 8 | 9 | # Create your views here. 10 | @staff_member_required(login_url=settings.LOGIN_URL) 11 | def addon_creator(request): 12 | message = "" 13 | form = AddonCreatorForm() 14 | if request.method == "POST": 15 | form = AddonCreatorForm(request.POST, request.FILES) 16 | if form.is_valid(): 17 | cleaned_form = form.cleaned_data 18 | # Create the addon 19 | zip_file_in_bytes = create_addon(cleaned_form) 20 | # Return the .zip file to the user 21 | response = HttpResponse(zip_file_in_bytes, content_type="application/zip") 22 | addon_id = cleaned_form["addon_id"] 23 | response['Content-Disposition'] = f'attachment; filename="{addon_id}.zip"' 24 | return response 25 | 26 | return render(request, "lac/generic_form.html", {"form": form, "heading": "Add-On Generator", "hide_buttons_top": "True", "action": "Generieren", "url": reverse("addons"), "description": "Hier können Sie in Sekunden ein Addon für Libre-Workspace erstellen. Es wird empfohlen, das Addon nach der Erstellung zu überprüfen und ggf. anzupassen.
Weitere Informationen zur Erstellung finden Sie hier: https://docs.libre-workspace.org/modules/addons.html"}) 27 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/app_dashboard/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/app_dashboard/__init__.py -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/app_dashboard/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | from .models import DashboardEntry 5 | 6 | admin.site.register(DashboardEntry) 7 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/app_dashboard/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AppDashboardConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'app_dashboard' 7 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/app_dashboard/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from .models import DashboardEntry 4 | 5 | class DashboardEntryForm(forms.ModelForm): 6 | def __init__(self, *args, **kwargs): 7 | super(DashboardEntryForm, self).__init__(*args, **kwargs) 8 | self.fields["icon"].required = False 9 | self.fields["icon"].widget.attrs["accept"] = "image/*" 10 | class Meta: 11 | model = DashboardEntry 12 | fields = ("title", "description", "link", "icon", "order", "is_active", "groups") 13 | labels = { 14 | "title": "Titel", 15 | "description": "Beschreibung", 16 | "link": "Link", 17 | "icon": "Icon", 18 | "order": "Reihenfolge (< 0: Vor den festen Icons, > 0: Hinter den festen Icons)", 19 | "is_active": "Aktiv", 20 | "groups": "Gruppen, die diesen Eintrag sehen können (Komma-separierte Liste). Leer lassen, um für alle sichtbar zu sein. Der Administator sieht immer alle Einträge." 21 | } 22 | 23 | class DashboardAppearanceForm(forms.Form): 24 | force_dark_mode = forms.BooleanField(label="Dunkles Design erzwingen", required=False) 25 | portal_branding_title = forms.CharField(label="Titel des Portals", required=False) 26 | portal_branding_logo = forms.ImageField(label="Logo des Portals", required=False, widget=forms.FileInput(attrs={"accept": "image/*"})) 27 | primary_color = forms.CharField(label="Primärfarbe (HEX-Code) (Bsp: #09928b)", required=False) 28 | secondary_color = forms.CharField(label="Sekundärfarbe (HEX-Code) (Bsp: #07746d)", required=False) 29 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/app_dashboard/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.19 on 2024-01-11 21:37 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='DashboardEntry', 16 | fields=[ 17 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('title', models.CharField(max_length=100)), 19 | ('description', models.CharField(max_length=1000)), 20 | ('link', models.CharField(max_length=1000)), 21 | ('icon', models.FileField(upload_to='dashboard_icons')), 22 | ('order', models.IntegerField(default=0)), 23 | ('is_active', models.BooleanField(default=True)), 24 | ], 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/app_dashboard/migrations/0002_dashboardentry_icon_url_dashboardentry_is_system.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 5.0.1 on 2024-02-03 20:54 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('app_dashboard', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='dashboardentry', 15 | name='icon_url', 16 | field=models.CharField(default='', max_length=1000), 17 | ), 18 | migrations.AddField( 19 | model_name='dashboardentry', 20 | name='is_system', 21 | field=models.BooleanField(default=False), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/app_dashboard/migrations/0003_dashboardentry_groups.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 5.0.1 on 2024-11-11 17:41 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('app_dashboard', '0002_dashboardentry_icon_url_dashboardentry_is_system'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='dashboardentry', 15 | name='groups', 16 | field=models.CharField(blank=True, default='', max_length=1000), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/app_dashboard/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/app_dashboard/migrations/__init__.py -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/app_dashboard/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Model: dasboard_entry 4 | class DashboardEntry(models.Model): 5 | title = models.CharField(max_length=100) 6 | description = models.CharField(max_length=1000) 7 | link = models.CharField(max_length=1000) 8 | icon = models.FileField(upload_to="dashboard_icons") 9 | icon_url = models.CharField(max_length=1000, default="") 10 | order = models.IntegerField(default=0) 11 | is_active = models.BooleanField(default=True) 12 | is_system = models.BooleanField(default=False) 13 | # comma separated list of group names which can see this entry 14 | # If this field is empty, all users (also not logged in) can see this entry 15 | groups = models.CharField(max_length=1000, default="", blank=True) 16 | 17 | def __str__(self): 18 | return self.title 19 | 20 | def to_dict(self): 21 | dict = { 22 | "id": self.id, 23 | "title": self.title, 24 | "description": self.description, 25 | "link": self.link, 26 | "icon_url": self.icon_url, 27 | "order": self.order, 28 | "is_active": self.is_active, 29 | "is_system": self.is_system, 30 | "groups": self.groups 31 | } 32 | if self.icon: 33 | dict["icon_url"] = self.icon.url 34 | return dict -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/app_dashboard/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | 4 | cfg = {} 5 | file_path = "/var/lib/libre-workspace/portal/app_dashboard_settings.json" 6 | 7 | 8 | # Save the configuration to the file as json 9 | def set_value(key, value): 10 | cfg[key] = value 11 | with open(file_path, "w") as file: 12 | file.write(json.dumps(cfg)) 13 | 14 | 15 | def get_value(key, default=None): 16 | if key in cfg: 17 | return cfg[key] 18 | if os.path.exists(file_path): 19 | try: 20 | with open(file_path, "r") as file: 21 | cfg.update(json.loads(file.read())) 22 | if key in cfg: 23 | return cfg[key] 24 | except: 25 | pass 26 | cfg[key] = default 27 | return default 28 | 29 | def get_all_values(): 30 | if os.path.exists(file_path): 31 | try: 32 | with open(file_path, "r") as file: 33 | cfg.update(json.loads(file.read())) 34 | except: 35 | pass 36 | return cfg -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/app_dashboard/templates/app_dashboard/app_dashboard_entries.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Dashboard-Einträge

5 | 6 | Neuer Dashboard-Eintrag 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {% for dashboard in dashboard_entries %} 15 | 16 | 17 | 18 | 19 | {% endfor %} 20 |
Titel Bearbeiten
{{ dashboard.title }} {% if not dashboard.is_active %} (Deaktiviert) {% endif %} Bearbeiten
21 | {% endblock %} 22 | 23 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/app_dashboard/templates/app_dashboard/index.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 | {% for array in grid %} 5 |
6 | {% for element in array %} 7 | {{element | safe}} 8 | {% endfor %} 9 |
10 | {% endfor %} 11 | 12 | {% if request.user.is_superuser %} 13 |
Dashboard-Einträge konfigurieren
14 |
Dashboard-Aussehen konfigurieren
15 | {% endif %} 16 | 17 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/app_dashboard/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/app_dashboard/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | urlpatterns = [ 6 | path("", views.index, name="index"), 7 | 8 | path("app_dashboard_entries", views.app_dashboard_entries, name="app_dashboard_entries"), 9 | path("new_app_dashboard_entry", views.new_app_dashboard_entry, name="new_app_dashboard_entry"), 10 | path("edit_app_dashboard_entry/", views.edit_app_dashboard_entry, name="edit_app_dashboard_entry"), 11 | path("delete_app_dashboard_entry/", views.delete_app_dashboard_entry, name="delete_app_dashboard_entry"), 12 | path("entries_json" , views.entries_json, name="entries_json"), 13 | path("app_dashboard_appearance" , views.app_dashboard_appearance, name="app_dashboard_appearance"), 14 | path("reset_app_dashboard_appearance" , views.reset_app_dashboard_appearance, name="reset_app_dashboard_appearance"), 15 | ] -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/idm/__init__.py -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class IdmConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'idm' 7 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/idm/migrations/__init__.py -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/idm/add_new_totp_device.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 |

Neues TOTP-Gerät hinzufügen

4 | 5 |
{% csrf_token %} 6 |

Name des Geräts

7 |

Geben Sie einen Namen für das Gerät ein, um es zu identifizieren.

8 | 9 | 10 | 11 |

QR-Code scannen

12 |

Scannen Sie den QR-Code mit Ihrer Authenticator-App.

13 | QR 14 | 15 |

Manuelle Eingabe

16 |

Wenn Sie den QR-Code nicht scannen können, geben Sie bitte den folgenden Schlüssel in Ihre Authenticator-App ein:

17 |

{{ base32_code }}

18 | 19 |

Code bestätigen

20 |

Geben Sie den Code ein, den Ihre Authenticator-App generiert hat.

21 | 22 | 23 | 24 |
25 |
26 | Zurück 27 |
28 | 29 |
30 |
31 | 32 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/idm/admin/assign_groups_to_user.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Gruppen-Mitgliedschaften von {{ user_information.displayName }}

5 | 6 | {% if message != "" %} 7 |

{{ message }}

8 | {% endif %} 9 | 10 |
{% csrf_token %} 11 | 12 | {% for group in groups %} 13 | 14 | 15 | 16 |
17 | 18 | {% endfor %} 19 |

20 |
21 |
22 | Zurück 23 |
24 | 25 |
26 |
27 | 28 | 29 | Hinweis: Einige Systemgruppen sind ausgeblendet. 30 | 31 | 32 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/idm/admin/assign_users_to_group.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Mitglieder der Gruppe {{cn}}

5 | 6 | {% if message != "" %} 7 |

{{ message }}

8 | {% endif %} 9 | 10 | Alle auswählen 11 | Alle abwählen 12 |

13 | 14 |
{% csrf_token %} 15 | 16 | {% for user in users %} 17 | 18 | 19 | 20 |
21 | 22 | {% endfor %} 23 |

24 |
25 |
26 | Zurück 27 |
28 | 29 |
30 |
31 | 32 | 33 | Hinweis: Einige Systembenutzer sind ausgeblendet. 34 | 35 | 36 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/idm/admin/create_group.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Gruppe hinzufügen

5 | 6 | {% if message != "" %} 7 |

{{ message }}

8 | {% endif %} 9 | 10 |
{% csrf_token %} 11 | {{ form }} 12 |

13 |
14 |
15 | Zurück 16 |
17 | 18 |
19 |
20 | 21 | 22 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/idm/admin/edit_group.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

'{{cn}}' bearbeiten

5 | 6 | {% if message != "" %} 7 |

{{ message }}

8 | {% endif %} 9 | 10 | 15 | 16 |
{% csrf_token %} 17 | {{ form }} 18 |

19 |
20 |
21 | Zurück 22 |
23 | 24 |
25 |
26 | 27 | 28 | 29 | {% comment %} Confirmation for User deletion {% endcomment %} 30 | 31 |
32 | 37 | 38 |

Gruppe wirklich löschen?

39 |

40 | Die Benutzer werden nicht gelöscht, sondern nur aus der Gruppe entfernt. 41 | Dieser Vorgang ist nicht mehr umkehrbar! 42 |

43 | 53 |
54 |
55 | 56 | {% endblock %} 57 | 58 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/idm/admin/edit_user.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

'{{cn}}' bearbeiten

5 | 6 | {% if message != "" %} 7 |

{{ message | safe }}

8 | {% endif %} 9 | 10 | 15 | 16 | 24 | 25 |
26 | 27 |
{% csrf_token %} 28 |
29 |
30 | Zurück 31 |
32 | 33 |
34 | {{ form }} 35 |

36 |
37 |
38 | Zurück 39 |
40 | 41 |
42 |
43 | 44 | 45 | 46 | {% comment %} Confirmation for User deletion {% endcomment %} 47 | 48 | 70 | 71 | 72 | {% endblock %} 73 | 74 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/idm/admin/group_overview.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Gruppenadministration

5 | 6 | Gruppe hinzufügen 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {% for group in groups %} 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | {% endfor %} 30 | 31 |
Gruppenname Beschreibung
{{group.cn}}{{group.description}}editgroup
32 | 33 | Hinweis: Einige Systemgruppen sind ausgeblendet. 34 | 35 | 36 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/idm/admin/user_overview.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Benutzeradministration

5 | 6 | Benutzer hinzufügen 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {% for user in users %} 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | {% endfor %} 30 | 31 |
Benutzername AnzeigenameE-Mail
{{user.cn}} {% if user.enabled == False %}(Deaktiviert){% endif %}{{user.displayName}}{{user.mail}}edit
32 | 33 | Hinweis: Einige Systembenutzer sind ausgeblendet. 34 | 35 | 36 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/idm/change_password.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Passwort ändern

5 | 6 | {% if message != "" %}

{{ message }}

{% endif %} 7 | 8 |
{% csrf_token %} 9 | {{ form }} 10 |
11 |
12 | Zurück 13 |
14 | 15 | 16 |
17 |
18 | 19 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/idm/dashboard.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Willkommen {{ user_information.displayName }}

5 | 6 | {% include "idm/libre_workspace_challenges.html" %} 7 | 8 | {% if user_information.admin %} 9 | 10 | 42 | 65 | 66 |

Eigene Einstellungen

67 | {% endif %} 68 | 69 | 70 | 95 | 96 | 97 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/idm/libre_workspace_challenges.html: -------------------------------------------------------------------------------- 1 | {% for challenge in challenges %} 2 |
3 | 6 |
7 | {% endfor %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/idm/login.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Anmelden

5 | 6 | 7 |
{% csrf_token %} 8 | 9 | 10 | 11 | 12 | 13 | 14 | {% if message %} 15 |

{{ message }}

16 | {% endif %} 17 | 18 | 19 | 20 | 25 |
26 | 27 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/idm/reset_password.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Passwort zurücksetzen

5 | 6 | 7 | {% if message != "" %} 8 |

{{ message }}

9 | {% endif %} 10 | 11 |
{% csrf_token %} 12 | 13 | {{ form }} 14 | 15 |
16 |
17 | Zurück 18 |
19 | 20 |
21 |
22 | 23 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/idm/user_settings.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Benutzereinstellungen

5 | 6 | {% if message != "" %} 7 |

{{ message | safe }}

8 | {% endif %} 9 | 10 | Passwort ändern 11 | 2-Faktor-Authentifizierung 12 | 13 |
14 | 15 |
{% csrf_token %} 16 | {{ form }} 17 |
18 |
19 | Zurück 20 |
21 | 22 |
23 |
24 | 25 | 26 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/oidc_provider/authorize.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Zugriffsanfrage

5 | 6 |

{{ client.name }} möchte auf folgende Informationen zugreifen ...

7 | 8 |
{% csrf_token %} 9 | 10 | {{ hidden_inputs }} 11 | 12 |
    13 | {% for scope in scopes %} 14 |
  • {{ scope.name }}
    {{ scope.description }}
  • 15 | {% endfor %} 16 |
17 | 18 | 19 | 20 |
21 | 22 | 23 |
24 | 25 |
26 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/oidc_provider/end_session_prompt.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 |

Abmeldung

4 | 5 | 10 | 11 |

Klicke hier, um die Abmeldung zu bestätigen.

12 | 13 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/templates/oidc_provider/error.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 |

{{ error }}

4 |

{{ description }}

5 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/idm/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | urlpatterns = [ 6 | path("dashboard", views.dashboard, name="dashboard"), 7 | path("login", views.user_login, name="user_login"), 8 | path("logout", views.user_logout, name="user_logout"), 9 | path("password_reset", views.user_password_reset, name="user_password_reset"), 10 | path("change_password", views.change_password, name="change_password"), 11 | path("user_settings", views.user_settings, name="user_settings"), 12 | 13 | path("create_totp_device", views.create_totp_device, name="create_totp_device"), 14 | path("delete_totp_device/", views.delete_totp_device, name="delete_totp_device"), 15 | path("otp_settings", views.otp_settings, name="otp_settings"), 16 | path("reset_2fa/", views.reset_2fa, name="reset_2fa"), 17 | 18 | path("user_overview", views.user_overview, name="user_overview"), 19 | path("create_user", views.create_user, name="create_user"), 20 | path("edit_user/", views.edit_user, name="edit_user"), 21 | path("delete_user/", views.delete_user, name="delete_user"), 22 | path("assign_groups_to_user/", views.assign_groups_to_user, name="assign_groups_to_user"), 23 | 24 | 25 | path("group_overview", views.group_overview, name="group_overview"), 26 | path("create_group", views.create_group, name="create_group"), 27 | path("edit_group/", views.edit_group, name="edit_group"), 28 | path("delete_group/", views.delete_group, name="delete_group"), 29 | path("assign_users_to_group/", views.assign_users_to_group, name="assign_users_to_group"), 30 | 31 | path("oidc_client_overview", views.oidc_client_overview, name="oidc_client_overview"), 32 | path("create_oidc_client", views.create_oidc_client, name="create_oidc_client"), 33 | path("edit_oidc_client/", views.edit_oidc_client, name="edit_oidc_client"), 34 | path("delete_oidc_client/", views.delete_oidc_client, name="delete_oidc_client"), 35 | 36 | ] -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/install.sh: -------------------------------------------------------------------------------- 1 | # This script is called directly after the installation of the .deb package 2 | # It is used to setup the django application and the caddy server 3 | 4 | sudo mkdir -p /var/www/libre-workspace-static/ 5 | sudo chmod -R 777 /var/www/libre-workspace-static/ 6 | 7 | # If the /etc/libre-workspace/portal/portal.conf file does not exist, then copy the example file 8 | if [ ! -f /etc/libre-workspace/portal/portal.conf ]; then 9 | sudo cp /etc/libre-workspace/portal/portal.conf.example /etc/libre-workspace/portal/portal.conf 10 | fi 11 | 12 | mkdir -p /var/lib/libre-workspace/portal/ 13 | cd /var/lib/libre-workspace/portal/ 14 | python3 -m venv venv 15 | cd - 16 | 17 | if [ ! -f /usr/bin/python ]; then 18 | sudo ln -s /usr/bin/python3 /usr/bin/python 19 | fi 20 | 21 | mkdir -p /var/lib/libre-workspace/modules/ 22 | 23 | source /var/lib/libre-workspace/portal/venv/bin/activate 24 | pip install --upgrade pip 25 | pip install -r /usr/lib/libre-workspace/portal/requirements.txt 26 | # Make sure that the database is up to date (sometimes e.g. oidc_provider needs to be updated) 27 | cd /usr/lib/libre-workspace/portal/ 28 | python3 manage.py makemigrations --no-input 29 | python manage.py migrate --no-input 30 | 31 | # Get the current IP-Adress 32 | # Get the output of hostname -I and cut the first part of it 33 | IP=`hostname -I | cut -d' ' -f1` 34 | 35 | # If caddy file does not has # PORTAL-ENTRY, then add it 36 | if ! grep -q "# PORTAL-ENTRY" /etc/caddy/Caddyfile; then 37 | 38 | # Remove :80 entry from caddy file, because we don't want to use it 39 | libre-workspace-remove-webserver-entry :80 40 | 41 | echo "# PORTAL-ENTRY 42 | :443 { 43 | tls internal { 44 | on_demand 45 | } 46 | handle_path /static* { 47 | root * /var/www/libre-workspace-static 48 | file_server 49 | encode zstd gzip 50 | } 51 | handle_path /media* { 52 | root * /var/lib/libre-workspace/portal/media 53 | file_server 54 | encode zstd gzip 55 | } 56 | reverse_proxy localhost:11123 57 | } 58 | 59 | # SED-LOCALHOST-ENTRY 60 | # We need this one for the local browser to work 61 | # Only http, because we don't want a warning about the self-signed certificate 62 | http://localhost { 63 | reverse_proxy https://localhost:443 { 64 | transport http { 65 | tls_insecure_skip_verify 66 | } 67 | } 68 | } 69 | 70 | " >> /etc/caddy/Caddyfile 71 | 72 | # If something is running on port 80, then systemctl restart caddy will silently hang 73 | systemctl restart caddy 74 | 75 | fi -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/__init__.py -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for lac project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'lac.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/icons/LICENSE: -------------------------------------------------------------------------------- 1 | # Material Icons from 2 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/icons/MaterialIcons-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/static/lac/icons/MaterialIcons-Regular.ttf -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/icons/company.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/static/lac/icons/company.webp -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/icons/desktop.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/static/lac/icons/desktop.webp -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/icons/element.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/static/lac/icons/element.webp -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/icons/jitsi.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/static/lac/icons/jitsi.webp -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/icons/libre-workspace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/static/lac/icons/libre-workspace.png -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/icons/libre-workspace.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/static/lac/icons/libre-workspace.webp -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/icons/lock.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/static/lac/icons/lock.webp -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/icons/nextcloud.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/static/lac/icons/nextcloud.webp -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/icons/xfce.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/static/lac/icons/xfce.png -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/images/background-2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/static/lac/images/background-2.webp -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/images/background-blured.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/static/lac/images/background-blured.webp -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/images/background.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/static/lac/images/background.webp -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/images/desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/static/lac/images/desktop.jpg -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/images/desktop_remote.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/lac/static/lac/images/desktop_remote.jpg -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/static/lac/js/modal.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Modal 3 | * 4 | * Pico.css - https://picocss.com 5 | * Copyright 2019-2023 - Licensed under MIT 6 | */ 7 | 8 | // Config 9 | const isOpenClass = "modal-is-open"; 10 | const openingClass = "modal-is-opening"; 11 | const closingClass = "modal-is-closing"; 12 | const animationDuration = 400; // ms 13 | let visibleModal = null; 14 | 15 | // Toggle modal 16 | const toggleModal = (event) => { 17 | event.preventDefault(); 18 | const modal = document.getElementById(event.currentTarget.getAttribute("data-target")); 19 | typeof modal != "undefined" && modal != null && isModalOpen(modal) 20 | ? closeModal(modal) 21 | : openModal(modal); 22 | }; 23 | 24 | // Is modal open 25 | const isModalOpen = (modal) => { 26 | return modal.hasAttribute("open") && modal.getAttribute("open") != "false" ? true : false; 27 | }; 28 | 29 | // Open modal 30 | const openModal = (modal) => { 31 | if (isScrollbarVisible()) { 32 | document.documentElement.style.setProperty("--scrollbar-width", `${getScrollbarWidth()}px`); 33 | } 34 | document.documentElement.classList.add(isOpenClass, openingClass); 35 | setTimeout(() => { 36 | visibleModal = modal; 37 | document.documentElement.classList.remove(openingClass); 38 | }, animationDuration); 39 | modal.setAttribute("open", true); 40 | }; 41 | 42 | // Close modal 43 | const closeModal = (modal) => { 44 | visibleModal = null; 45 | document.documentElement.classList.add(closingClass); 46 | setTimeout(() => { 47 | document.documentElement.classList.remove(closingClass, isOpenClass); 48 | document.documentElement.style.removeProperty("--scrollbar-width"); 49 | modal.removeAttribute("open"); 50 | }, animationDuration); 51 | }; 52 | 53 | // Close with a click outside 54 | document.addEventListener("click", (event) => { 55 | if (visibleModal != null) { 56 | const modalContent = visibleModal.querySelector("article"); 57 | const isClickInside = modalContent.contains(event.target); 58 | !isClickInside && closeModal(visibleModal); 59 | } 60 | }); 61 | 62 | // Close with Esc key 63 | document.addEventListener("keydown", (event) => { 64 | if (event.key === "Escape" && visibleModal != null) { 65 | closeModal(visibleModal); 66 | } 67 | }); 68 | 69 | // Get scrollbar width 70 | const getScrollbarWidth = () => { 71 | // Creating invisible container 72 | const outer = document.createElement("div"); 73 | outer.style.visibility = "hidden"; 74 | outer.style.overflow = "scroll"; // forcing scrollbar to appear 75 | outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps 76 | document.body.appendChild(outer); 77 | 78 | // Creating inner element and placing it in the container 79 | const inner = document.createElement("div"); 80 | outer.appendChild(inner); 81 | 82 | // Calculating difference between container's full width and the child width 83 | const scrollbarWidth = outer.offsetWidth - inner.offsetWidth; 84 | 85 | // Removing temporary elements from the DOM 86 | outer.parentNode.removeChild(outer); 87 | 88 | return scrollbarWidth; 89 | }; 90 | 91 | // Is scrollbar visible 92 | const isScrollbarVisible = () => { 93 | return document.body.scrollHeight > screen.height; 94 | }; -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/templates.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.urls import reverse 3 | 4 | def process_overview_dict(overview : dict) -> dict: 5 | """ 6 | Process the overview dictionary and returns the processed dictionary 7 | """ 8 | overview["add_url"] = reverse(overview["add_url_name"]) 9 | if overview["element_url_key"] is None: 10 | overview["element_url_key"] = overview["t_keys"][0] 11 | overview["table_content"] = [] 12 | overview["first_t_heading"] = overview["t_headings"].pop(0) 13 | 14 | # We extract the first field of the normal table because then we can not center the first column in jinja 15 | for i in range(len(overview["elements"])): 16 | element = overview["elements"][i] 17 | row = {} 18 | row["first_field"] = _get_attr(element, overview["t_keys"][0]) 19 | row_content = [] 20 | for j in range(1, len(overview["t_keys"])): 21 | key = overview["t_keys"][j] 22 | row_content.append(_get_attr(element, key)) 23 | row["content"] = row_content 24 | if overview.get("info_url_name", None) is not None: 25 | row["info_url"] = reverse(overview["info_url_name"], args=[_get_attr(element, overview["element_url_key"])]) 26 | if overview.get("edit_url_name", None) is not None: 27 | row["edit_url"] = reverse(overview["edit_url_name"], args=[_get_attr(element, overview["element_url_key"])]) 28 | if overview.get("delete_url_name", None) is not None: 29 | row["delete_url"] = reverse(overview["delete_url_name"], args=[_get_attr(element, overview["element_url_key"])]) 30 | overview["table_content"].append(row) 31 | 32 | return overview 33 | 34 | 35 | def _get_attr(obj, attr): 36 | value = None 37 | if hasattr(obj, "__getitem__"): 38 | value = obj[attr] 39 | else: 40 | value = getattr(obj, attr) 41 | if str(value) == "True": 42 | value = "✅" 43 | elif str(value) == "False": 44 | value = "-" 45 | elif value is None: 46 | value = "-" 47 | return value 48 | 49 | def message(request, message : str, url_name : str = "", url_args : list = []): 50 | if url_name == "": 51 | url_name = "index" 52 | # Check if url_name can be reversed or its a direct url 53 | try: 54 | reverse(url_name, args=url_args) 55 | except: 56 | return render(request, "lac/message.html", {"message": message, "url": url_name}) 57 | 58 | return render(request, "lac/message.html", {"message": message, "url": reverse(url_name, args=url_args)}) -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/templates/lac/confirm.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

5 | 6 | 7 |
{{ message | safe }}
8 | 9 |
10 | 11 |
{% csrf_token %} 12 | 13 | 14 | 15 | 16 |
17 |
18 | Zurück 19 |
20 | 21 |
22 |
23 | 24 | 25 | {% endblock %} 26 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/templates/lac/create_x.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 | {% if heading %} 5 |

{{ heading }}

6 | {% else %} 7 |

Erstelle {{ type }}

8 | {% endif %} 9 | 10 | {% if message and message != "" %} 11 |
12 | 20 |
21 | {% endif %} 22 | 23 |
{% csrf_token %} 24 | {% if hide_buttons_top %} 25 | 26 | {% else %} 27 |
28 |
29 | Zurück 30 |
31 | 32 |
33 | {% endif %} 34 | {{ form }} 35 |

36 |
37 |
38 | Zurück 39 |
40 | 41 |
42 |
43 | 44 | {% endblock %} 45 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/templates/lac/edit_x.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Bearbeite {{ name }}

5 | 6 | {% if description %} {{ description | safe }}

{% endif %} 7 | 8 | {% if message and message != "" %} 9 |
10 | 18 |
19 | {% endif %} 20 | 21 | 22 | {% if delete_url %} 23 | 28 | {% endif %} 29 | 30 |
{% csrf_token %} 31 |
32 |
33 | Zurück 34 |
35 | 36 |
37 | {{ form }} 38 |

39 |
40 |
41 | Zurück 42 |
43 | 44 |
45 |
46 | 47 | 48 | {% comment %} Confirmation for deletion {% endcomment %} 49 | 50 | 72 | 73 | 74 | {% endblock %} 75 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/templates/lac/generic_form.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 | {% if heading %} 5 |

{{ heading }}

6 | {% endif %} 7 | 8 | {% if message and message != "" %} 9 |
10 | 18 |
19 | {% endif %} 20 | 21 | {% if description != "" %} 22 |

{{ description | safe }}

23 | {% endif %} 24 | 25 |
{% csrf_token %} 26 | {% if hide_buttons_top %} 27 | 28 | {% else %} 29 |
30 |
31 | Zurück 32 |
33 | 34 |
35 | {% endif %} 36 | {{ form }} 37 |

38 |
39 |
40 | Zurück 41 |
42 | 43 |
44 |
45 | 46 | {% if additional_content %} 47 | {{ additional_content | safe }} 48 | {% endif %} 49 | 50 | {% endblock %} 51 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/templates/lac/message.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

5 | 6 | 7 |
{{ message | safe }}
8 | 9 |
10 | 11 |
12 |
13 | Weiter 14 |
15 |
16 | 17 | 18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/templates/lac/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: / -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/urls.py: -------------------------------------------------------------------------------- 1 | """lac URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.2/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path, include 18 | from django.conf import settings 19 | from django.conf.urls.static import static 20 | from django.views.generic.base import TemplateView 21 | 22 | urlpatterns = [ 23 | path("idm/", include("idm.urls")), 24 | path("unix/", include("unix.urls")), 25 | path("welcome/", include("welcome.urls")), 26 | path("addon_creator/", include("addon_creator.urls")), 27 | path("m23software/", include("m23software.urls")), 28 | path("", include("app_dashboard.urls")), 29 | path('openid/', include('oidc_provider.urls', namespace='oidc_provider')), 30 | path( 31 | "robots.txt", 32 | TemplateView.as_view(template_name="lac/robots.txt", content_type="text/plain"), 33 | ), 34 | ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 35 | 36 | if settings.ADMIN_ENABLED: 37 | urlpatterns += [ 38 | path("admin/", admin.site.urls), 39 | ] -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/lac/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for lac project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'lac.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/m23software/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/m23software/__init__.py -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/m23software/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/m23software/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class M23SoftwareConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'm23software' 7 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/m23software/connector.py: -------------------------------------------------------------------------------- 1 | import os 2 | import requests 3 | 4 | 5 | M23_API_KEY = os.getenv("M23_API_KEY", "") 6 | URL_BASE = f"http://localhost:12934/rest.php?api_key={M23_API_KEY}&cmd=" 7 | 8 | # http://localhost/rest.php?api_key=HY3R8rOC4sadFxvS9ucwAGZNP71oWJV0&cmd=getProfiles 9 | # example: ["Debian 12 KDE"] 10 | def get_profiles(): 11 | """ 12 | Fetches the list of profiles from the m23 API. 13 | Returns a dictionary with profile names as keys and their IDs as values. 14 | """ 15 | response = requests.get(f"{URL_BASE}getProfiles") 16 | if response.status_code == 200: 17 | profile_names = response.json() 18 | choices = [(name.replace(" ", ""), name) for name in profile_names] 19 | return choices 20 | else: 21 | raise Exception(f"Failed to fetch profiles: {response.status_code} - {response.text}") 22 | 23 | 24 | 25 | 26 | # /** 27 | # **description Gives out precalculated network settings (eg. next free IP that can be uses for an m23 client). 28 | # **url rest.php?api_key=[key]&cmd=getNetworkSettingsProposal 29 | # **/ 30 | 31 | # $proposedNetworkSettings = array(); 32 | # $proposedNetworkSettings['ip'] = CLIENT_getNextFreeIp(); 33 | # $proposedNetworkSettings['netmask'] = getServerNetmask(); 34 | # $proposedNetworkSettings['gateway'] = getServerGateway(); 35 | 36 | # $dns1dns2 = getDNSServers(); 37 | # $proposedNetworkSettings['dns1'] = $dns1dns2[0]; 38 | # $proposedNetworkSettings['dns2'] = $dns1dns2[1]; 39 | 40 | # $proposedNetworkSettings['bootTypes'] = CClient::getNetworkBootTypesArrayForSelection(); 41 | # echo(json_encode($proposedNetworkSettings)); 42 | 43 | def get_network_settings_proposal(): 44 | """ 45 | Fetches the proposed network settings for a new m23 client. 46 | Returns a dictionary with the proposed IP, netmask, gateway, DNS servers, and boot types. 47 | """ 48 | response = requests.get(f"{URL_BASE}getNetworkSettingsProposal") 49 | 50 | if response.status_code == 200: 51 | return response.json() 52 | else: 53 | raise Exception(f"Failed to fetch network settings proposal: {response.status_code} - {response.text}") 54 | 55 | 56 | def addClient(client, ip, netmask, gateway, dns1, dns2, mac, boottype, login, password, rootpassword, profile): 57 | """ 58 | Adds a new client to m23 with the specified parameters. 59 | Returns the response from the m23 API. 60 | """ 61 | params = { 62 | "client": client, 63 | "ip": ip, 64 | "netmask": netmask, 65 | "gateway": gateway, 66 | "dns1": dns1, 67 | "dns2": dns2, 68 | "mac": mac, 69 | "boottype": boottype, 70 | "login": login, 71 | "password": password, 72 | "rootpassword": rootpassword, 73 | "profile": profile 74 | } 75 | 76 | response = requests.get(f"{URL_BASE}addClient", params=params) 77 | 78 | if response.status_code == 200: 79 | return response.json() 80 | else: 81 | raise Exception(f"Failed to add client: {response.status_code} - {response.text}") 82 | 83 | 84 | def get_client_list(group=None): 85 | """ 86 | Fetches the list of clients from m23. 87 | Returns a list of client names. 88 | """ 89 | 90 | group_appendix = "" 91 | if group: 92 | group_appendix = f"&group={group}" 93 | 94 | response = requests.get(f"{URL_BASE}getClientList{group_appendix}") 95 | 96 | if response.status_code == 200: 97 | return response.json() 98 | else: 99 | raise Exception(f"Failed to fetch client list: {response.status_code} - {response.text}") -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/m23software/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/m23software/migrations/__init__.py -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/m23software/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/m23software/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/m23software/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | urlpatterns = [ 6 | path("client_install", views.install_client, name="m23software.install_client"), 7 | path("client_list", views.m23_client_list, name="m23software.client_list"), 8 | path("client_detail/", views.m23_client_detail, name="m23software.client_detail"), 9 | path("client_delete/", views.m23_client_delete, name="m23software.client_delete"), 10 | ] -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'lac.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/openbox-autostart: -------------------------------------------------------------------------------- 1 | # This file is used for autostart of the browser 2 | 3 | # If .config/chromium folder exists remove it 4 | rm -rf ~/.config/chromium 5 | 6 | # Because the portal page could not be ready, we need to wait a bit 7 | sleep 10 8 | 9 | chromium --kiosk --temp-profile --noerrdialogs --enable-features=OverlayScrollbar --disable-restore-session-state http://localhost 10 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/prepare_for_first_boot.sh: -------------------------------------------------------------------------------- 1 | # This script is run once at first boot of the fresh installed system. 2 | 3 | # Configure automatic login for user "systemv" 4 | sed -i "s/^#autologin-user=.*/autologin-user=systemv/" "/etc/lightdm/lightdm.conf" 5 | sed -i "s/^#autologin-user-timeout=.*/autologin-user-timeout=0/" "/etc/lightdm/lightdm.conf" 6 | 7 | 8 | # Add autostart file for the openbox desktop environment 9 | cp /usr/lib/libre-workspace/portal/openbox-autostart /etc/xdg/openbox/autostart -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/requirements.txt: -------------------------------------------------------------------------------- 1 | django 2 | python-ldap 3 | django-auth-ldap 4 | gunicorn 5 | requests 6 | django-oidc-provider 7 | image 8 | django_otp 9 | qrcode 10 | Jinja2 -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/__init__.py: -------------------------------------------------------------------------------- 1 | import unix.unix_scripts.unix 2 | 3 | unix.unix_scripts.unix.generate_local_admin_token() -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class BackupsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'backups' 7 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/email.py: -------------------------------------------------------------------------------- 1 | import os 2 | from django.core.mail import EmailMessage 3 | from django.conf import settings 4 | 5 | # If this one returns None the mail was sent successfully 6 | def send_mail(recipients: list, subject, message, attachment_path=""): 7 | if not are_mail_settings_configured(): 8 | return "Email settings are not configured" 9 | email = EmailMessage(subject=subject, body=message, from_email=settings.EMAIL_HOST_EMAIL, to=recipients) 10 | # Check also if attachment_path exists 11 | if attachment_path != "" and attachment_path is not None and os.path.exists(attachment_path): 12 | email.attach_file(attachment_path) 13 | print("Sending email with subject: " + subject + " to: " + str(recipients)) 14 | try: 15 | email.send() 16 | except Exception as e: 17 | error_message = "Error while sending email: " + str(e) 18 | print(error_message) 19 | return error_message 20 | 21 | 22 | def are_mail_settings_configured(): 23 | return settings.EMAIL_HOST_USER and settings.EMAIL_HOST_EMAIL and settings.EMAIL_HOST_PASSWORD and settings.EMAIL_HOST and settings.EMAIL_PORT 24 | 25 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/unix/migrations/__init__.py -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/templates/unix/backup_settings.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 | {% if message != "" %} 5 |

{{ message }}

6 | {% endif %} 7 | 8 |

Systemverwaltung

9 | 10 |

Vollautomatisierte Backups

11 |

Grundlegende Informationen

12 |

13 | Der komplette Server inklusive Daten wird mit allen Konfigurationen vollautomatisiert täglich über borg auf einen externen Ort gesichert. 14 | Das Wiederherstellen von Daten ist aktuell nur manuell durch einen Systemadministrator möglich. 15 | Diese Backups sind nur für den Fall eines Systemausfalls in der letzten Not gedacht. 16 | Die einzelnen Sicherungsstände werden inkrementell gespeichert und komprimiert und sind somit sehr platzsparend. 17 |

18 | 19 |

Anleitung

20 |
    21 |
  • Stellen Sie sicher, dass auf dem anderen Server borg installiert ist. sudo apt install borgbackup
  • 22 |
  • Es ist empfohlen, für die Backups einen eigenen Benutzer auf dem anderen Ort zu erstellen. Dieser Benutzer sollte nur die Rechte haben, die für die Backups notwendig sind.
  • 23 |
  • Sie müssen sicherstellen, dass sich der Server auf dem anderen Ort anmelden kann. Fügen Sie hierfür den öffentlichen Schlüssel dieses Servers (ganz unten angegeben) in die Datei ~/.ssh/authorized_keys auf dem anderen Ort ein.
  • 24 |
  • Erstellen sie mit dem Befehl borg init --encryption=repokey ein neues Repository.
  • 25 |
  • Fügen Sie den SSH-Fingerabdruck des Backup-Servers in das entsprechende Feld unten. Sie können sich ihn mit dem Befehl ssh-keyscan -p <port> <IP-Adresse/Hostname> anzeigen lassen.
  • 26 |
27 | 28 | 29 |
{% csrf_token %} 30 | {{ form }} 31 |

32 |
33 |
34 | Zurück 35 |
36 | 37 |
38 | 41 |
42 | Hinweis: Während des Backups werden alle Dienste vorübergehend abgeschaltet. 43 |
44 |
45 | 46 | 47 |

Aktueller öffentlicher Schlüssel

48 | {{ public_key }} 49 | 50 |

Mit diesem Schlüssel kann sich der Server automatisch auf dem anderen Ort anmelden.

51 | 52 |

Wichtige Sicherheitshinweise

53 | 57 | 58 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/templates/unix/critical_system_configuration.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Kritische Systemkonfiguration

5 | 6 | 9 | 10 | 27 | 28 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/templates/unix/data_export.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |

Datenexport

4 | 5 | {% if data_export_status != "running" %} 6 | 7 | {% comment %} Rsync log {% endcomment %} 8 | {% if rsync_history != "" %} 9 | 10 | 14 | Nachrichten des letzten Exports ansehen 15 | 16 | 17 | 18 | 19 |
20 | 25 | 26 |

Nachrichten des letzten Exports

27 |

Je weniger Nachrichten zu sehen sind, desto fehlerfreier ist der letzte Export verlaufen.

28 | 29 | {{ rsync_history | safe }} 30 | 31 | 40 |
41 |
42 |
43 |
44 | {% endif %} 45 | 46 |

47 | Wähle eine Partition aus, auf der alle Daten des Servers exportiert werden sollen. 48 | Es werden alle wichtigen Daten (auch von eingebundenen Festplatten) gesichert, welche nicht in /mnt oder /media eingehängt sind.
49 | Sollte schon ein Export dieses Servers auf dem Ziel existieren, werden die Daten auf dem Export überschrieben/aktualisiert. 50 | Es wird nicht überprüft, ob auf dem Ziel genügend Speicherplatz vorhanden ist. 51 |

52 | 53 |
{% csrf_token %} 54 | 55 | 69 | 70 |
71 | 72 |

Hinweis: Es werden während des Export-Vorgangs alle Dienste vorrübergehend ausgeschaltet.

73 | {% else %} 74 |

75 | Der Daten-Export läuft gerade. Bitte warte, bis der Export abgeschlossen ist. 76 | Dieser Vorgang kann einige Stunden dauern. 77 | Alle weiteren Dienste werden gerade pausiert und sind aktuell nicht erreichbar. 78 |

79 | Abbrechen 80 | {% endif %} 81 | 82 | 83 | 84 | 85 |
-------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/templates/unix/data_import.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |

Datenimport (Nextcloud)

4 | 5 | {% if nextcloud_import_process_running %} 6 | 7 |

8 | Der Datenimport läuft gerade. Bitte warte, bis der Importier-Vorgang abgeschlossen ist. 9 | Dieser Vorgang kann einige Stunden dauern. 10 | Erst ganz am Ende des Vorgangs werden die Daten in der Nextcloud sichtbar.
11 |

12 | Abbrechen 13 | {% else %} 14 | 15 | 16 | 17 |

18 | Dieses Tool ermöglicht es, Daten von einer Festplatte auf die Nextcloud zu importieren. 19 | Die Daten werden dabei in den Nextcloud Bereich eines bestimmten Nutzers kopiert. 20 | Erst ganz am Ende des Vorgangs werden die Daten in der Nextcloud sichtbar.
21 | Möchten Sie die Daten in einen Gruppenordner importieren, so müssen Sie die Daten zunächst in den Nextcloud Bereich eines Nutzers importieren und anschließend in den Gruppenordner verschieben. 22 |

23 | 24 | 25 |
{% csrf_token %} 26 | 27 | 33 | 34 | 40 | 41 |
42 |

Im nächsten Schritt wird der Ordner auf der Quell-Festplatte ausgewählt, den Sie importieren möchten.

43 | 44 | {% endif %} 45 | 46 |
-------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/templates/unix/data_management.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Datenimport/-export

5 | 6 | {% include "unix/mounting.html" %} 7 | 8 | {% include "unix/data_export.html" %} 9 | 10 | {% if nextcloud_user_directories|length > 0 %} 11 | {% include "unix/data_import.html" %} 12 | {% endif %} 13 | 14 |
Hinweis: Diese Seite aktualisiert sich alle 60 Sekunden.
15 | 16 | 21 | 22 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/templates/unix/email_configuration.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

E-Mail Konfiguration

5 | 6 |

7 | Um die volle Funktionalität auszuschöpfen, wird empfohlen, ein Mail-Konto anzugeben, über dies der Libre-Workspace selbständig Einladungen, 8 | "Passwort-Zurücksetzen"-Mails oder weiteres versenden kann. 9 |

10 | 11 | {% if message != "" %} 12 |

{{ message }}

13 | {% endif %} 14 | 15 | Test-Mail senden 16 | 17 | 18 |
{% csrf_token %} 19 | {{ form }} 20 | 21 |
22 |
23 | Zurück 24 |
25 | 26 |
27 |
28 | 29 | 30 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/templates/unix/file_explorer.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 | {% include "unix/folder_view.html" %} 5 | 6 | 7 | 10 | 11 |
12 |
13 | Hinweis: Aus Sicherheitsgründen, ist es nicht möglich, den Inhalt von Dateien anzuzeigen. 14 |
15 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/templates/unix/folder_view.html: -------------------------------------------------------------------------------- 1 |
{% csrf_token %} 2 | 3 | 6 |
7 | 8 |
Aktueller Ordner: {{ current_directory }}
9 | 10 | 11 | 12 | 13 | {% for folder in folder_list %} 14 | 15 | {% csrf_token %} 16 | 17 | 21 | 22 | 23 | {% endfor %} 24 | 25 | {% for file in file_list %} 26 | 27 | {% csrf_token %} 28 | 32 | 33 | 34 | {% endfor %} 35 | 36 |
-------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/templates/unix/mounting.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |

Festplatten

4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% for partition in partitions %} 16 | 17 | 18 | 19 | 20 | 29 | {% endfor %} 30 | 31 |
PartitionGrößeEinhängepunktAktionen
{{ partition.name }}{{ partition.size }}{% if partition.mountpoint %}{% endif %}{{ partition.mountpoint}} 21 | {% if partition.mountpoint != "/"%} 22 | {% if partition.mountpoint %} 23 | Aushängen 24 | {% else %} 25 | Einhängen 26 | {% endif %} 27 | {% endif %} 28 |
32 | 33 |
-------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/templates/unix/pick_folder.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Ordner auswählen

5 | 6 |

{{ description }}

7 | 8 | {% include "unix/folder_view.html" %} 9 | 10 | 11 |
12 |
{% csrf_token %} 13 | 14 |
15 | 19 |
20 |
21 |
{% csrf_token %} 22 | 23 | 26 |
27 |
28 | 29 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/templates/unix/system_configuration.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Systemkonfiguration

5 | 6 | 37 | 38 | 69 | 70 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/templates/unix/system_management.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Systemverwaltung

5 | 6 | {% include "unix/system_dashboard.html" %} 7 | 8 | {% include "unix/backup_dashboard.html" %} 9 | 10 | {% include "unix/update_management.html" %} 11 | 12 |
Hinweis: Diese Seite aktualisiert sich alle 60 Sekunden.
13 | 14 | 19 | 20 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/.gitignore: -------------------------------------------------------------------------------- 1 | disabled 2 | id_rsa.pub 3 | trusted_fingerprints 4 | unix.conf 5 | run_service 6 | backup_disabled 7 | upgradable_packages 8 | export_data 9 | os 10 | env.sh 11 | app_dashboard_settings.json -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/cfg.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # Config service which edits and gets the config in the cfg file 4 | 5 | def get_config_path(): 6 | if os.path.isfile("/etc/libre-workspace/portal/portal.conf"): 7 | return "/etc/libre-workspace/portal/portal.conf" 8 | else: 9 | return "!ERROR: cfg file not found!" 10 | 11 | def get_value(key, default): 12 | # Open cfg file 13 | with open(get_config_path(), "r") as f: 14 | # Read all lines 15 | lines = f.readlines() 16 | # Iterate over all lines 17 | for line in lines: 18 | line_parts = line.split("=") 19 | if line_parts[0].replace(" ", "").replace("export", "") == key: 20 | # If the value is surrounded by " ", remove them 21 | if line_parts[1].strip().startswith("\"") and line_parts[1].strip().endswith("\""): 22 | return line_parts[1].strip()[1:-1] 23 | else: 24 | return line_parts[1].strip() 25 | 26 | 27 | return default 28 | 29 | def set_value(key, value): 30 | # Open cfg file 31 | with open(get_config_path(), "r") as f: 32 | # Read all lines 33 | lines = f.readlines() 34 | # Iterate over all lines 35 | settings_found = False 36 | for i in range(len(lines)): 37 | line = lines[i] 38 | line_parts = line.split("=") 39 | if line_parts[0].replace(" ", "").replace("export", "") == key: 40 | lines[i] = f'export {key}="{value}"\n' 41 | settings_found = True 42 | 43 | if not settings_found: 44 | lines.append(f'export {key}="{value}"\n') 45 | 46 | # Write all lines back to the cfg file 47 | with open(get_config_path(), "w") as f: 48 | f.writelines(lines) -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/do_data_export.sh: -------------------------------------------------------------------------------- 1 | # The path of the destination is stored in file "export_data" 2 | DESTINATION=`cat ./export_data` 3 | 4 | touch export_running 5 | 6 | # Dump all databases 7 | mysqldump -u root --all-databases --default-character-set=utf8mb4 > /mysql_all_databases.sql 8 | 9 | # Disable all services 10 | bash ./stop_services.sh 11 | 12 | echo "Starting export to $DESTINATION..." 13 | 14 | # Copy all files with rsync 15 | rsync -a --delete / $DESTINATION --exclude /dev --exclude /proc --exclude /sys --exclude /tmp --exclude /run --exclude /media --exclude /mnt --exclude /var/log > /var/lib/libre-workspace/portal/history/rsync.log 16 | 17 | # Enable all services 18 | bash ./start_services.sh 19 | 20 | rm export_running 21 | rm export_data 22 | 23 | echo "Export finished!" -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/general/basics.sh: -------------------------------------------------------------------------------- 1 | export DEBIAN_FRONTEND=noninteractive 2 | 3 | apt update 4 | apt dist-upgrade -y 5 | apt install ufw vim docker.io docker-compose apparmor htop curl -y 6 | 7 | # Set the password of the systemv user 8 | chpasswd <<<"systemv:$ADMIN_PASSWORD" 9 | 10 | ufw allow http 11 | ufw allow https 12 | ufw allow ssh 13 | ufw --force enable 14 | 15 | # Remove the default caddy service if it exists 16 | python3 ../remove_caddy_service.py :80 17 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/general/install.sh: -------------------------------------------------------------------------------- 1 | # This will be removed in the setup_rest_of_linux_arbeitsplatz.sh script. 2 | 3 | touch /var/lib/libre-workspace/portal/installation_running 4 | echo "Starting installation..." 5 | 6 | # This script installs the whole libre-workspace how defined in the environment variables. 7 | cd /usr/lib/libre-workspace/portal/unix/unix_scripts/general 8 | echo "Doing installations basics..." 9 | . basics.sh 10 | 11 | # Install SAMBA DC if the environment variable SAMBA_DC is not empty 12 | if [ ! -z "$SAMBA_DC" ]; then 13 | echo "Doing samba dc installation..." 14 | # Install SAMBA DC 15 | cd /usr/lib/libre-workspace/modules/samba_dc 16 | . setup_samba_dc.sh 17 | fi 18 | 19 | # Distribute the certificates for local installations 20 | if [ $DOMAIN = "int.de" ] ; then 21 | echo "Setting up internal https..." 22 | cd /usr/lib/libre-workspace/portal/unix/unix_scripts/general 23 | . setup_internal_https.sh 24 | fi 25 | 26 | # If the environment variable NEXTCLOUD is not empty 27 | if [ ! -z "$NEXTCLOUD" ]; then 28 | echo "Nextcloud installation..." 29 | # Install Nextcloud 30 | cd /usr/lib/libre-workspace/modules/nextcloud 31 | . setup_nextcloud.sh 32 | fi 33 | 34 | # If the environment variable COLLABORA is not empty 35 | if [ ! -z "$COLLABORA" ]; then 36 | echo "Collabora installation..." 37 | # Install Collabora 38 | cd /usr/lib/libre-workspace/modules/collabora 39 | . setup_collabora.sh 40 | fi 41 | 42 | # If the environment variable ONLYOFFICE is not empty 43 | if [ ! -z "$ONLYOFFICE" ]; then 44 | echo "Onlyoffice installation..." 45 | # Install Onlyoffice 46 | cd /usr/lib/libre-workspace/modules/onlyoffice 47 | . setup_onlyoffice.sh 48 | fi 49 | 50 | # If the environment variable DESKTOP is not empty 51 | if [ ! -z "$DESKTOP" ]; then 52 | echo "Desktop installation..." 53 | # Install Desktop 54 | cd /usr/lib/libre-workspace/modules/desktop 55 | . setup_desktop.sh 56 | fi 57 | 58 | # If the environment variable MATRIX is not empty 59 | if [ ! -z "$MATRIX" ]; then 60 | echo "Matrix installation..." 61 | # Install Matrix 62 | cd /usr/lib/libre-workspace/modules/matrix 63 | . setup_matrix.sh 64 | fi 65 | 66 | # If the environment variable JITSI is not empty 67 | if [ ! -z "$JITSI" ]; then 68 | echo "Jitsi installation..." 69 | # Install Jitsi 70 | cd /usr/lib/libre-workspace/modules/jitsi 71 | . setup_jitsi.sh 72 | fi 73 | 74 | # If the environment variable XFCE is not empty 75 | if [ ! -z "$XFCE" ]; then 76 | echo "XFCE installation..." 77 | # Install XFCE 78 | cd /usr/lib/libre-workspace/modules/xfce 79 | . setup_xfce.sh 80 | fi 81 | 82 | # Install the rest of the libre-workspace 83 | echo "Setting up the rest of the libre-workspace..." 84 | cd /usr/lib/libre-workspace/portal/unix/unix_scripts/general 85 | . /usr/lib/libre-workspace/portal/unix/unix_scripts/general/setup_rest_of_libre-workspace.sh -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/general/patches/2024-08-01_dns_forwarder_only.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get the current file name 4 | FILE_NAME=$(basename $0) 5 | # Get the date of the filename which is like this: 2024-06-25 6 | DATE=${FILE_NAME:0:10} 7 | # Check if the file is older than 365 days 8 | if [ $(( ($(date +%s) - $(date -d $DATE +%s)) / 86400 )) -gt 365 ]; then 9 | echo "Patch is older than 365 days. Exiting patch." 10 | exit 0 11 | fi 12 | 13 | # Check if we need to apply the patch 14 | # Check if "dns forwarder resolve only" is set in /etc/samba/smb.conf. If not, then exit the patch. 15 | if ! grep -q "dns forwarder resolve only" /etc/samba/smb.conf; then 16 | echo "dns forwarder resolve only is not set in /etc/samba/smb.conf. Exiting patch." 17 | exit 0 18 | fi 19 | 20 | # Remove "dns forwarder resolve only" from /etc/samba/smb.conf 21 | sed -i '/dns forwarder resolve only/d' /etc/samba/smb.conf 22 | 23 | # Update November 2024: 24 | # The "dns forwarder resolve only" option is no longer supported in Samba 4.16 and later. 25 | # So we remove the option from the configuration file to avoid any issues. 26 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/general/patches/2024-12-13_ignore_admin_users_nextcloud.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get the current file name 4 | FILE_NAME=$(basename $0) 5 | # Get the date of the filename which is like this: 2024-06-25 6 | DATE=${FILE_NAME:0:10} 7 | # Check if the file is older than 365 days 8 | if [ $(( ($(date +%s) - $(date -d $DATE +%s)) / 86400 )) -gt 365 ]; then 9 | echo "Patch is older than 365 days. Exiting patch." 10 | exit 0 11 | fi 12 | 13 | # Check if we need to apply the patch 14 | # Check if "IGNORE_ADMIN_STATUS_FOR_NEXTCLOUD_USERS" is in /etc/libre-workspace/portal/portal.conf 15 | # If this is set then exit the patch 16 | if grep -q "IGNORE_ADMIN_STATUS_FOR_NEXTCLOUD_USERS" /etc/libre-workspace/portal/portal.conf; then 17 | echo "IGNORE_ADMIN_STATUS_FOR_NEXTCLOUD_USERS is set in /etc/libre-workspace/portal/portal.conf. Exiting patch." 18 | exit 0 19 | fi 20 | 21 | # Add "IGNORE_ADMIN_STATUS_FOR_NEXTCLOUD_USERS" to /etc/libre-workspace/portal/portal.conf 22 | echo " 23 | # Don't change the admin status for these nextcloud users automatically also if they are not in group "Domain Admin". Separate them with , 24 | export IGNORE_ADMIN_STATUS_FOR_NEXTCLOUD_USERS="" 25 | " >> /etc/libre-workspace/portal/portal.conf 26 | 27 | systemctl restart libre-workspace-service.service -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/general/patches/2025_05_09_fix_fail2ban_ond_deb12.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # IS THIS PATCH OLDER THAN 365 DAYS? 4 | # Get the current file name 5 | FILE_NAME=$(basename $0) 6 | # Get the date of the filename which is like this: 2024-06-25 7 | DATE=${FILE_NAME:0:10} 8 | # Check if the file is older than 365 days 9 | if [ $(( ($(date +%s) - $(date -d $DATE +%s)) / 86400 )) -gt 365 ]; then 10 | echo "Patch is older than 365 days. Exiting patch." 11 | exit 0 12 | fi 13 | 14 | 15 | # Check if we need to apply the patch 16 | # Check if -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/general/setup_internal_https.sh: -------------------------------------------------------------------------------- 1 | # This script should be run as root 2 | # We need this variables: 3 | # DOMAIN 4 | # IP 5 | # ADMIN_PASSWORD 6 | export DEBIAN_FRONTEND=noninteractive 7 | 8 | 9 | apt install libnss3-tools 10 | caddy trust 11 | update-ca-certificates 12 | 13 | mkdir -p /var/www/cert/ 14 | cp /etc/ssl/certs/Caddy_Local_Authority_* /var/www/cert/lan.crt 15 | 16 | echo "$IP cert.$DOMAIN" >> /etc/hosts # Domain itself 17 | 18 | # If samba-tool is installed: 19 | if [ -f /usr/bin/samba-tool ]; then 20 | samba-tool dns add la.$DOMAIN $DOMAIN cert A $IP -U administrator%$ADMIN_PASSWORD 21 | fi 22 | 23 | echo "cert.int.de { 24 | tls internal 25 | root * /var/www/cert/ 26 | file_server browse 27 | } 28 | 29 | " >> /etc/caddy/Caddyfile 30 | 31 | systemctl restart caddy -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/general/update_email_settings.py: -------------------------------------------------------------------------------- 1 | # Import Settings: 2 | import lac.settings as settings 3 | import unix.unix_scripts.unix as unix 4 | import os 5 | 6 | # email_settings: 7 | # { 8 | # "server": "", 9 | # "port": "", 10 | # "user": "", 11 | # "password": "", 12 | # "encryption": "", # Optios: "TLS", "SSL" 13 | # } 14 | def update_email_settings(email_settings): 15 | # Change the email settings for lac on the fly 16 | settings.EMAIL_HOST = email_settings["server"] 17 | settings.EMAIL_PORT = email_settings["port"] 18 | settings.EMAIL_HOST_USER = email_settings["user"] 19 | settings.EMAIL_HOST_EMAIL = email_settings["email"] 20 | settings.EMAIL_HOST_PASSWORD = email_settings["password"] 21 | if email_settings["encryption"] == "TLS": 22 | settings.EMAIL_USE_TLS = "True" 23 | settings.EMAIL_USE_SSL = "False" 24 | else: 25 | settings.EMAIL_USE_TLS = "False" 26 | settings.EMAIL_USE_SSL = "True" 27 | 28 | # Change email settings in nextcloud if nextcloud is installed 29 | if unix.is_nextcloud_installed(): 30 | from_adress = email_settings["email"].split("@")[0] 31 | mail_domain = email_settings["email"].split("@")[1] 32 | os.system(f'sudo -u www-data php {settings.NEXTCLOUD_INSTALLATION_DIRECTORY}/occ config:system:set mail_smtpauthtype --value="LOGIN"') 33 | os.system(f'sudo -u www-data php {settings.NEXTCLOUD_INSTALLATION_DIRECTORY}/occ config:system:set mail_smtpmode --value="smtp"') 34 | os.system(f'sudo -u www-data php {settings.NEXTCLOUD_INSTALLATION_DIRECTORY}/occ config:system:set mail_smtpsecure --value="{email_settings["encryption"]}"') 35 | os.system(f'sudo -u www-data php {settings.NEXTCLOUD_INSTALLATION_DIRECTORY}/occ config:system:set mail_sendmailmode --value="smtp"') 36 | os.system(f'sudo -u www-data php {settings.NEXTCLOUD_INSTALLATION_DIRECTORY}/occ config:system:set mail_smtphost --value="{email_settings["server"]}"') 37 | os.system(f'sudo -u www-data php {settings.NEXTCLOUD_INSTALLATION_DIRECTORY}/occ config:system:set mail_smtpport --value="{email_settings["port"]}"') 38 | os.system(f'sudo -u www-data php {settings.NEXTCLOUD_INSTALLATION_DIRECTORY}/occ config:system:set mail_domain --value="{mail_domain}"') 39 | os.system(f'sudo -u www-data php {settings.NEXTCLOUD_INSTALLATION_DIRECTORY}/occ config:system:set mail_from_address --value="{from_adress}"') 40 | os.system(f'sudo -u www-data php {settings.NEXTCLOUD_INSTALLATION_DIRECTORY}/occ config:system:set mail_smtpauth --value="1"') 41 | os.system(f'sudo -u www-data php {settings.NEXTCLOUD_INSTALLATION_DIRECTORY}/occ config:system:set mail_smtpname --value="{email_settings["user"]}"') 42 | os.system(f'sudo -u www-data php {settings.NEXTCLOUD_INSTALLATION_DIRECTORY}/occ config:system:set mail_smtppassword --value="{email_settings["password"]}"') 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/get_ip.sh: -------------------------------------------------------------------------------- 1 | IP_ADDR=$(hostname -I | cut -d' ' -f1) 2 | echo $IP_ADDR -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/import_folder_to_nextcloud_user.sh: -------------------------------------------------------------------------------- 1 | touch nextcloud_import_process_running 2 | 3 | # Get date in format: yyyy-mm-dd-hh-mm-ss 4 | DATE=$(date +"%Y%m%d%H%M%S") 5 | 6 | mkdir -p $NEXTCLOUD_USER_FOLDER/Import-$DATE/ 7 | cp -r $FOLDER_IMPORT $NEXTCLOUD_USER_FOLDER/Import-$DATE/ 8 | convmv -f utf-8 -t utf-8 -r --notest --nfc $NEXTCLOUD_USER_FOLDER/* 9 | sudo chown www-data:www-data -R $NEXTCLOUD_USER_FOLDER/* 10 | 11 | # One of these two commands will work (because we do not know if the current nextcloud has apc.enable_cli=1 or not): 12 | sudo -u www-data php $NEXTCLOUD_INSTALLATION_DIRECTORY/occ files:scan --all 13 | rm nextcloud_import_process_running -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/maintenance/.gitignore: -------------------------------------------------------------------------------- 1 | start_additional_services.sh 2 | stop_additional_services.sh -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/maintenance/cleanup.sh: -------------------------------------------------------------------------------- 1 | apt clean 2 | apt autoremove -y 3 | 4 | docker image prune -a -f 5 | docker volume prune -f 6 | 7 | sudo journalctl --vacuum-size=1G 8 | 9 | # To address the possible memory leak described in https://github.com/Jean28518/libre-workspace/issues/92 10 | systemctl restart libre-workspace-portal.service -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/maintenance/do_update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source /etc/libre-workspace/libre-workspace.conf 3 | 4 | touch /var/lib/libre-workspace/portal/update_running 5 | 6 | CURRENT_TIME=`date +"%Y-%m-%d_%H-%M-%S"` 7 | 8 | echo "$CURRENT_TIME: Starting update..." > /var/lib/libre-workspace/portal/history/update.log 9 | 10 | apt-get update >> /var/lib/libre-workspace/portal/history/update.log 11 | 12 | DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y >> /var/lib/libre-workspace/portal/history/update.log 13 | 14 | rm /var/lib/libre-workspace/portal/update_running -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/maintenance/mount_backups.sh: -------------------------------------------------------------------------------- 1 | source /etc/libre-workspace/libre-workspace.conf 2 | 3 | mkdir -p /backups 4 | 5 | # If encrypted == true, then use this command: 6 | if [ $BORG_ENCRYPTION = true ] ; then 7 | export BORG_PASSPHRASE=$BORG_PASSPHRASE 8 | else 9 | export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes 10 | fi 11 | 12 | if [ -z "$REMOTEPATH" ] ; then 13 | borg mount $BORG_REPOSITORY /backups 14 | else 15 | borg mount --remote-path $REMOTEPATH $BORG_REPOSITORY /backups 16 | fi -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/maintenance/recover_path.sh: -------------------------------------------------------------------------------- 1 | # This script recovers a file or directory from the backup and copies it to the original location 2 | # The backup has to be mounted before running this script 3 | 4 | # The path to recover is in the first argument 5 | RECOVER_PATH="$1" 6 | # Ensure that path ends not with a slash 7 | RECOVER_PATH=${RECOVER_PATH%/} 8 | 9 | # The path where we want to copy the recovered file(s) can be dereived also from the first argument 10 | # The first argument has the path /backups/YYYY-MM-DD/ 11 | # Remove /backups/YYYY-MM-DD/ from the path and use the rest as the destination path 12 | DESTINATION_PATH=${RECOVER_PATH#/backups/*/} 13 | DESTINATION_PATH=/$DESTINATION_PATH 14 | # DESTINATION_PATH is now /path/to/recover/ 15 | # Remove the last folder from the path 16 | DESTINATION_PATH=${DESTINATION_PATH%/*} 17 | 18 | # If we are now at the root of the filesystem, then we have to add a slash to the path 19 | if [ -z "$DESTINATION_PATH" ]; then 20 | DESTINATION_PATH=/ 21 | fi 22 | 23 | 24 | touch recovering_in_progress 25 | PARENT_DIR=$(dirname "$DESTINATION_PATH") 26 | mkdir -p "$PARENT_DIR" 27 | cp -ra "$RECOVER_PATH" "$DESTINATION_PATH" 28 | 29 | if [ $? -ne 0 ]; then 30 | echo "Failed to recover $RECOVER_PATH to $DESTINATION_PATH" 31 | rm recovering_in_progress 32 | exit 1 33 | fi 34 | 35 | echo "Recovered "$RECOVER_PATH" to "$DESTINATION_PATH"" 36 | 37 | # If the path has "nextcloud" in it, then we have to rescan the files 38 | if [[ $RECOVER_PATH == *"nextcloud"* ]]; then 39 | sudo -u www-data php /var/www/nextcloud/occ files:scan --all 40 | fi 41 | rm recovering_in_progress -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/maintenance/start_services.sh: -------------------------------------------------------------------------------- 1 | # Get the current php version 2 | PHP_VERSION=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;') 3 | 4 | systemctl start mariadb 5 | systemctl start php$PHP_VERSION-fpm 6 | systemctl start docker 7 | 8 | # Turn on maintenance mode of Nextcloud 9 | if [ -f /var/www/nextcloud/occ ]; then 10 | sudo -u www-data /usr/bin/php /var/www/nextcloud/occ maintenance:mode --off 11 | fi 12 | 13 | # If file start_additional_services.sh exists, run it 14 | if [ -f /var/lib/libre-workspace/portal/start_additional_services.sh ]; then 15 | bash /var/lib/libre-workspace/portal/start_additional_services.sh 16 | fi 17 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/maintenance/stop_services.sh: -------------------------------------------------------------------------------- 1 | . umount_backups.sh 2 | 3 | # Turn off maintenance mode of Nextcloud 4 | if [ -f /var/www/nextcloud/occ ]; then 5 | sudo -u www-data /usr/bin/php /var/www/nextcloud/occ maintenance:mode --on 6 | fi 7 | 8 | # Get the current php version 9 | PHP_VERSION=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;') 10 | 11 | systemctl stop docker 12 | systemctl stop php$PHP_VERSION-fpm 13 | systemctl stop mariadb 14 | 15 | # If file stop_additional_services.sh exists, run it 16 | if [ -f /var/lib/libre-workspace/portal/stop_additional_services.sh ]; then 17 | bash /var/lib/libre-workspace/portal/stop_additional_services.sh 18 | fi 19 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/maintenance/umount_backups.sh: -------------------------------------------------------------------------------- 1 | borg umount /backups -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/unix_config.py: -------------------------------------------------------------------------------- 1 | # This code is duplicated in the unix.py file for internal use. 2 | # We need this for our service.py because it does not like the unix.py file. 3 | import os 4 | 5 | 6 | # Change current directory to the directory of this script 7 | os.chdir(os.path.dirname(os.path.realpath(__file__))) 8 | 9 | # If the config file does not exist, create it 10 | if not os.path.isfile("/etc/libre-workspace/libre-workspace.conf"): 11 | os.system("touch /etc/libre-workspace/libre-workspace.conf") 12 | 13 | 14 | config = {} 15 | 16 | def read_config_file(): 17 | # Read the config file 18 | for line in open("/etc/libre-workspace/libre-workspace.conf"): 19 | if line.strip().startswith("#"): 20 | continue 21 | if "=" not in line: 22 | continue 23 | key, value = line.split("=", 1) 24 | # remove the " and ' characters from the outer ends of the string 25 | config[key.strip()] = value.strip("'\"\n ") 26 | 27 | def write_config_file(): 28 | # Write the config file 29 | with open("/etc/libre-workspace/libre-workspace.conf", "w") as f: 30 | for key, value in config.items(): 31 | if value == "true" or value == "false" or value.isnumeric(): 32 | f.write(f"{key}={value}\n") 33 | else: 34 | f.write(f"{key}=\"{value}\"\n") 35 | 36 | 37 | def get_value(key, default=""): 38 | read_config_file() 39 | # Get the value of a key from the config file 40 | if key in config: 41 | return config[key] 42 | else: 43 | return default 44 | 45 | 46 | def set_value(key, value): 47 | read_config_file() 48 | value = str(value) 49 | # Set the value of a key in the config file 50 | if value != "": 51 | config[key] = value 52 | elif key in config: 53 | del config[key] 54 | print(f"Setting {key} to {value}") 55 | write_config_file() -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/unix/unix_scripts/utils.py: -------------------------------------------------------------------------------- 1 | # To this file unix.py (django) and also service.py (not django) can access 2 | import subprocess 3 | 4 | 5 | def is_backup_running(): 6 | # Check if a process with the name backup.sh in it is running 7 | return "backup.sh" in subprocess.getoutput("ps -aux") 8 | 9 | 10 | def get_ram_usage(): 11 | rv = {} 12 | rv["total_ram"] = subprocess.getoutput("free -h").split("\n")[1].split()[1].replace("Gi", "").replace("Mi", "") 13 | ram_usage = subprocess.getoutput("free -h").split("\n")[1].split()[2] 14 | if "Mi" in ram_usage: 15 | rv["ram_usage"] = str(int(ram_usage.replace("Mi", ""))/1024).replace(".", ",") 16 | else: 17 | rv["ram_usage"] = ram_usage.replace("Gi", "") 18 | rv["ram_percent"] = int(float(rv["ram_usage"].replace(",", ".")) / float(rv["total_ram"].replace(",", ".")) * 100) 19 | 20 | return rv 21 | 22 | 23 | def get_cpu_usage(five_min=False): 24 | if five_min: 25 | load_avg = subprocess.getoutput("cat /proc/loadavg").split(" ")[1] 26 | else: 27 | load_avg = subprocess.getoutput("cat /proc/loadavg").split(" ")[0] 28 | cpu_number = subprocess.getoutput("nproc") 29 | return int(float(load_avg) / float(cpu_number) * 100) 30 | 31 | 32 | def get_disks_stats(): 33 | # Return disk name, the mountpoint, the foll size and the used size. 34 | lines = subprocess.getoutput("df -h") 35 | 36 | lines = lines.split("\n") 37 | lines = lines[1:] 38 | disks = [] 39 | for line in lines: 40 | if "error" in line.lower() or "warning" in line.lower(): 41 | continue 42 | line = line.split(" ") 43 | while '' in line: 44 | line.remove('') 45 | name = line[0] 46 | if "/dev/loop" in name or "udev" in name or "tmpfs" in name or "overlay" in name or "fuse" in name or "bindfs" in name: 47 | continue 48 | size = line[1] 49 | # If the size is in megabytes, skip this disk, because it is very small 50 | if "M" in size: 51 | continue 52 | disk = {} 53 | disk["name"] = name.replace("/dev/", "") 54 | disk["size"] = size 55 | disk["used"] = line[2] 56 | disk["used_percent"] = line[4].replace("%", "") 57 | disk["mountpoint"] = line[5] 58 | try: 59 | float(disk["size"].replace("G", "").replace("T", "").replace("M", "").replace("K", "").replace(",", "")) 60 | float(disk["used"].replace("G", "").replace("T", "").replace("M", "").replace("K", "").replace(",", "")) 61 | float(disk["used_percent"]) 62 | disks.append(disk) 63 | except: 64 | continue 65 | return disks -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/update_libre_workspace.sh: -------------------------------------------------------------------------------- 1 | # Get current installed version of Libre Workspace 2 | INSTALLED_VERSION=$(dpkg -s libre-workspace | grep Version | cut -d " " -f 2) 3 | 4 | # Get latest version of Libre Workspace from GitHub 5 | LATEST_VERSION=$(curl -s https://api.github.com/repos/Jean28518/libre-workspace/releases/latest | grep tag_name | cut -d '"' -f 4) 6 | 7 | # If the installed version is the same as the latest version, then exit 8 | if [ "v$INSTALLED_VERSION" == "$LATEST_VERSION" ]; then 9 | echo "Libre Workspace is already up to date. Exiting..." 10 | exit 0 11 | fi 12 | 13 | wget https://github.com/Jean28518/libre-workspace/releases/latest/download/libre-workspace.deb 14 | 15 | # If libre-workspace.deb is not a file, then exit 16 | if [ ! -f "libre-workspace.deb" ]; then 17 | echo "libre-workspace.deb file not found. Canceling Libre Workspace Update..." 18 | exit 1 19 | fi 20 | 21 | apt-get install ./libre-workspace.deb -y 22 | rm libre-workspace.deb 23 | 24 | # Update all pip packages 25 | if [ -d "/var/lib/libre-workspace/portal/venv/bin" ]; then 26 | source /var/lib/libre-workspace/portal/venv/bin/activate 27 | else 28 | 29 | fi 30 | pip install --upgrade pip 31 | pip install --upgrade -r /usr/lib/libre-workspace/portal/requirements.txt 32 | 33 | 34 | # Make sure, both services are enabled and running 35 | systemctl enable libre-workspace-service 36 | systemctl enable libre-workspace-portal 37 | systemctl restart libre-workspace-* -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/welcome/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/welcome/__init__.py -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/welcome/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/welcome/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class WelcomeConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'welcome' 7 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/welcome/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jean28518/libre-workspace/8a3d700f288ac0c986556191c0e0c8e4878cb66d/src/usr/lib/libre-workspace/portal/welcome/migrations/__init__.py -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/welcome/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/welcome/templates/welcome/.gitignore: -------------------------------------------------------------------------------- 1 | access_rendered.html -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/welcome/templates/welcome/installation_running.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Installation...

5 | 6 | {% if message != "" %}

{{ message }}

{% endif %} 7 | 8 |

9 | Vielen Dank für Ihre Zeit!
Libre-Workspace installiert sich nun selbstständig. Dies kann einige Minuten dauern.
10 | Diese Seite kann zu manchen Zeitpunkten nicht erreichbar sein. Bitte stellen Sie sicher, dass der Server eine durchgehende, stabile Internetverbindung hat.
11 |

12 | 13 |

Nach der Installation startet Ihr Server neu. Dann ist Libre-Workspace einsatzbereit!

14 | 15 | 16 |
17 |
18 | 19 |
20 | download 21 |
22 | 23 |
24 |
25 | 26 |

27 | {%include "welcome/access.html"%} 28 |

29 | 30 | {% endblock %} 31 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/welcome/templates/welcome/libreworkspace_lite.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Libre Workspace Lite

5 | 6 |

7 | Sie haben keine Module ausgewählt. Dadurch wird nun Libre Workspace Lite installiert. 8 | Dies bedeutet, dass lediglich das Portal mit der dahinterliegenden Verwaltung installiert wird. Das zentrale Nutzermanagement wird ebenfalls erstmal nicht installiert. 9 | Dies ist optimal für die Administration eines einfachen Linux-Servers. Ein vergleichbares Projekt (mit anderen Funktionen) ist bspw. Cockpit. 10 | Sollten Sie zu einem späteren Zeitpunkt Module oder AddOns installieren wollen, ist dies nach der Installation jederzeit wie gewohnt möglich über das Portal möglich. 11 |

12 | 13 |

Erreichbarkeit des Portals

14 | 15 | {% if message != "" %}

{{ message }}

{% endif %} 16 | 17 |
{% csrf_token %} 18 |
19 | 23 | 27 |
28 | 29 | 38 | 39 | 44 | 45 |
46 | 47 | 48 |
49 | 50 | 63 | 64 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/welcome/templates/welcome/welcome_dns_settings.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Sichtbarkeit

5 | 6 |

7 | Wählen Sie aus, ob Libre-Workspace öffentlich oder lediglich im lokalen Netzwerk erreichbar sein soll. 8 | Dies kann später nur noch manuell durch einen wissenden Linux-Administrator geändert werden. 9 |

10 | 11 | 12 | {% if message != "" %}

{{ message }}

{% endif %} 13 | 14 |
{% csrf_token %} 15 |
16 | 20 | 24 |
25 | 26 | 48 | 49 | 50 | 51 | 52 |
53 | 54 |

Erklärung

55 | 56 | 57 |

Lokal

58 | 59 |

60 | Libre-Workspace ist nur im lokalen Netzwerk (Zuhause) erreichbar. Sie können sich nur von Geräten aus Ihrem lokalen Netzwerk mit Ihrem Benutzerkonto anmelden. 61 |
62 |

63 | 64 |

Öffentlich

65 | 66 |

67 | Libre-Workspace ist über das Internet erreichbar. Sie können sich von überall auf der Welt mit Ihrem Benutzerkonto anmelden. 68 | Dies ist in der späteren Benutzung die einfachste Möglichkeit, um auf Libre-Workspace zuzugreifen. 69 |
70 |

71 | 72 | 73 | 86 | 87 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/welcome/templates/welcome/welcome_select_apps.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Module

5 | 6 |

Wählen Sie aus, welche Module installiert werden sollen.

7 | 8 | {% if message != "" %}

{{ message }}

{% endif %} 9 | 10 |
{% csrf_token %} 11 |

Cloud

12 |
13 | 18 |
19 | 20 | 27 | 28 |
29 | 34 |
35 | 36 | 37 |

Kommunikation

38 |
39 | 44 | 45 | 50 |
51 | 52 |

Weitere Module

53 |
54 | 59 |
60 | 61 | 62 | 63 |
64 | 65 | 77 | 78 | {% endblock %} 79 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/welcome/templates/welcome/welcome_start.html: -------------------------------------------------------------------------------- 1 | {% extends "lac/base.html" %} 2 | {% block content %} 3 | 4 |

Willkommen!

5 | 6 |

In den nächsten Seiten werden wir gemeinsam Libre-Workspace einrichten. Bitte definieren Sie zunächst ein sicheres Masterpasswort.
7 | Das Passwort muss mindestens 8 Zeichen lang sein, und Sonderzeichen, Zahlen und Buchstaben enthalten. 8 |

9 | {% if message != "" %}

{{ message }}

{% endif %} 10 | 11 |
{% csrf_token %} 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |

Tipp: Sie können die Einrichtung auch von einem anderen Gerät aus vornehmen: https://{{ ip }}

22 | 23 | {% endblock %} -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/welcome/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /src/usr/lib/libre-workspace/portal/welcome/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | urlpatterns = [ 6 | path("start", views.welcome_start, name="welcome_start"), 7 | path("select_apps", views.welcome_select_apps, name="welcome_select_apps"), 8 | path("dns_settings", views.welcome_dns_settings, name="welcome_dns_settings"), 9 | path("libreworkspace_lite", views.libreworkspace_lite, name="libreworkspace_lite"), 10 | path("installation_running", views.installation_running, name="installation_running"), 11 | path("access", views.access, name="access"), 12 | path("etc_hosts", views.etc_hosts, name="etc_hosts"), 13 | ] -------------------------------------------------------------------------------- /src/usr/lib/systemd/system/libre-workspace-portal.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Libre Workspace Portal Service 3 | 4 | [Service] 5 | Type=simple 6 | RemainAfterExit=yes 7 | WorkingDirectory=/ 8 | ExecStart=libre-workspace-portal 9 | Restart=on-failure 10 | RestartSec=5 11 | User=root 12 | Group=root 13 | 14 | [Install] 15 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /src/usr/lib/systemd/system/libre-workspace-service.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Libre Workspace Service. Runs commands which are issued from web and automatic actions. 3 | 4 | [Service] 5 | Type=simple 6 | RemainAfterExit=yes 7 | WorkingDirectory=/ 8 | ExecStart=/usr/bin/libre-workspace-service 9 | Restart=on-failure 10 | RestartSec=5 11 | User=root 12 | Group=root 13 | 14 | [Install] 15 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /tests/oidc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OIDC RP 6 | 7 | 8 | 9 | 10 |
11 |

OpenID Connect RP Example

12 | 13 |

By Nat Sakimura

14 | 15 | 16 | 17 |
18 |

How to use

19 |
    20 |
  • Serve this file at a separate web server and access this via webbrowser.
  • 21 |
  • Adjust the redirect_uri in this file to the url whith which you can access this file.
  • 22 |
  • Add a OIDC client in /idm/create_oidc_client on your Libre Workspace instance
  • 23 |
  • Don't forget to add the redirect_uri to the allowed redirect_uris in the client configuration.
  • 24 |
  • Insert the generated client id in this file.
  • 25 |
  • Adjust the libre workspace url in this file.
  • 26 |
  • You are ready to login! If everything works, you will see a info box of your webbrowser with all user information.
  • 27 |
  • If you have trouble open the developer console of your webbrowser to see the error messages and access some mentioned urls manually.
  • 28 |
29 | 30 | 31 | 32 | 33 | 73 | 74 | 75 | --------------------------------------------------------------------------------