Compare commits

...

8 Commits

Author SHA1 Message Date
Priit Jõerüüt
53e7fb013c
Translated using Weblate (Estonian)
Currently translated at 19.9% (389 of 1948 strings)
2026-08-11 10:51:27 +00:00
Coucouf
ba0b39c2a4
Translated using Weblate (French)
Currently translated at 100.0% (1948 of 1948 strings)
2026-08-11 10:51:24 +00:00
Sunil Mohan Adapa
c5f9606f43
pyproject: Declare support for Django 6.0
Explicitly noting down the version of Django helps us keep better track of our
upgrade progress. Due to the nature of changes to Django in recent versions,
FreedomBox does not need any changes to support newer versions. So, work done on
analyzing support for newer versions needs to tracked separate from git log
message.

Tests:

- Building FreedomBox Debian package works.

Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2026-08-08 10:03:49 -04:00
Sunil Mohan Adapa
5013c05d35
settings: Drop support for Django < 4.0
- Trixie has Django 4.2.28.

Tests:

- Unit tests pass on Trixie and Forky.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2026-08-08 10:03:46 -04:00
Sunil Mohan Adapa
f2e898090c
mypy: Add support for version 2.1
Tests:

- Unit tests pass.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2026-08-08 10:03:44 -04:00
Sunil Mohan Adapa
d2a959a277
tests: Use class methods for class scoped fixtures
Using class-scoped fixture as instance method is deprecated in pytest 9.1 and
support will be removed in 10.0.

See: https://docs.pytest.org/en/stable/deprecations.html#class-scoped-fixture-as-instance-method

Tests:

- Run functional tests for samba, matrixsynapse (unrelated failure), and
bepasty.

Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2026-08-08 10:03:39 -04:00
Sunil Mohan Adapa
c1aeb1f661
d/postinst: Remove unnecessary file
- The last bit code left in the file was a fix applied in 2018 and not used
since we stopped using access.conf file.

Tests:

- Building Debian package works.

- The Debian package still contains a postinst script with code for starting
systemd daemon and for running other debhelper hooks.

- Installing the Debian package on a fresh Debian trixie machine starts the
FreedomBox service. First wizard finished without issues and bepasty app install
succeeds.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2026-08-08 09:11:38 -04:00
Sunil Mohan Adapa
841b0382e7
homeassistant: App is stable, remove experimental warning
- This app has been running on my FreedomBox without any problems with every day
usage for more than 6 months.

Tests:

- The app description does not show experimental message anymore. App page shows
up fine.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2026-08-08 09:09:42 -04:00
12 changed files with 78 additions and 112 deletions

View File

@ -1,13 +0,0 @@
#!/bin/sh
set -e
# Due to a change in sudo, now it runs PAM modules even on password-less
# invocations. This leads to plinth not being able to run root privileges. This
# is because of our own restrictions in /etc/security/access.conf. Since Plinth
# is locked out after upgrade, we need to do this in postinst.
sed -i 's+-:ALL EXCEPT root fbx (admin) (sudo):ALL+-:ALL EXCEPT root fbx plinth (admin) (sudo):ALL+' /etc/security/access.conf
#DEBHELPER#
exit 0

View File

@ -45,10 +45,10 @@ box_name = 'FreedomBox'
# Other globals
develop = False
config_files = []
config_files: list[str] = []
def expand_to_dot_d_paths(file_paths):
def expand_to_dot_d_paths(file_paths: list[str]) -> list[str]:
"""Expand a list of file paths to include file.d/* also."""
final_list = []
for file_path in file_paths:
@ -65,7 +65,7 @@ def expand_to_dot_d_paths(file_paths):
return final_list
def get_develop_config_path():
def get_develop_config_path() -> str:
"""Return config path of current source folder for development mode."""
root_directory = os.path.dirname(os.path.realpath(__file__))
root_directory = os.path.realpath(root_directory)
@ -73,7 +73,7 @@ def get_develop_config_path():
return config_path
def get_config_paths():
def get_config_paths() -> list[str]:
"""Get default config paths."""
return [
'/usr/share/freedombox/freedombox.config',
@ -82,14 +82,14 @@ def get_config_paths():
]
def read():
def read() -> None:
"""Read all configuration files."""
config_paths = get_config_paths()
for config_path in expand_to_dot_d_paths(config_paths):
read_file(config_path)
def read_file(config_path):
def read_file(config_path: str):
"""Read and merge into defaults a single configuration file."""
if not os.path.isfile(config_path): # Does not throw exceptions
# Ignore missing configuration files
@ -101,9 +101,9 @@ def read_file(config_path):
parser = configparser.ConfigParser(
defaults={
'parent_dir':
pathlib.Path(config_path).parent.resolve(),
str(pathlib.Path(config_path).parent.resolve()),
'parent_parent_dir':
pathlib.Path(config_path).parent.parent.resolve(),
str(pathlib.Path(config_path).parent.parent.resolve()),
})
parser.read(config_path) # Ignores all read errors
@ -123,6 +123,7 @@ def read_file(config_path):
)
for section, name, datatype in config_items:
value: int | str | bool
try:
value = parser.get(section, name)
except (configparser.NoSectionError, configparser.NoOptionError):

View File

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-07-29 02:26+0000\n"
"PO-Revision-Date: 2026-01-09 20:01+0000\n"
"PO-Revision-Date: 2026-08-11 10:51+0000\n"
"Last-Translator: Priit Jõerüüt <jrthwlate@users.noreply.hosted.weblate.org>\n"
"Language-Team: Estonian <https://hosted.weblate.org/projects/freedombox/"
"freedombox/et/>\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.15.1\n"
"X-Generator: Weblate 2026.9.dev0\n"
#: plinth/config.py:103
#, python-brace-format
@ -167,7 +167,7 @@ msgstr "Veebiliides (Plinth) {box_name}"
#: plinth/modules/apache/__init__.py:129
msgid "Web app protected by FreedomBox"
msgstr ""
msgstr "Veebirakendust kaitseb FreedomBox"
#: plinth/modules/apache/components.py:234
#, python-brace-format
@ -398,10 +398,8 @@ msgid "Passphrase"
msgstr "Salafraas"
#: plinth/modules/backups/forms.py:187
#, fuzzy
#| msgid "Passphrase; Only needed when using encryption."
msgid "Only needed when using encryption."
msgstr "Salafraasi on vaja vaid krüptimise kasutamisel."
msgstr "Seda on vaja vaid krüptimise kasutamisel."
#: plinth/modules/backups/forms.py:190
msgid "Confirm Passphrase"
@ -945,7 +943,7 @@ msgstr ""
#: plinth/modules/bepasty/forms.py:33
#: plinth/modules/bepasty/templates/bepasty.html:32
msgid "Comment"
msgstr "Komentaar"
msgstr "Kommentaar"
#: plinth/modules/bepasty/forms.py:34
msgid "Any comment to help you remember the purpose of this password."
@ -5925,10 +5923,8 @@ msgid "OpenID Connect Provider"
msgstr ""
#: plinth/modules/oidc/templates/oauth2_provider/authorize.html:14
#, fuzzy
#| msgid "Application installed."
msgid "Application"
msgstr "Rakendus on paigaldatud."
msgstr "Rakendus"
#: plinth/modules/oidc/templates/oauth2_provider/authorize.html:22
msgid "Authorize App"
@ -6884,7 +6880,7 @@ msgstr ""
#: plinth/modules/security/templates/security_report.html:45
msgid "App Name"
msgstr "Rakendus"
msgstr "Rakenduse nimi"
#: plinth/modules/security/templates/security_report.html:46
msgid "Current Vulnerabilities"
@ -8694,10 +8690,8 @@ msgid "Log in with passkey"
msgstr ""
#: plinth/modules/users/templates/users_passkey_edit.html:19
#, fuzzy
#| msgid "Update setup"
msgid "Update Passkey"
msgstr "Uuenda seadistust"
msgstr "Uuenda pääsuvõtit"
#: plinth/modules/users/templates/users_passkeys.html:30
msgid "Adding passkey failed: "
@ -8726,26 +8720,20 @@ msgstr ""
#: plinth/modules/users/templates/users_passkeys.html:83
#: plinth/modules/users/templates/users_passkeys.html:85
#, fuzzy
#| msgid "Add password"
msgid "Add passkey"
msgstr "Lisa salasõna"
msgstr "Lisa pääsuvõti"
#: plinth/modules/users/templates/users_passkeys.html:93
#, fuzzy
#| msgid "Domain"
msgid "For Domain"
msgstr "Domeen"
msgstr "Domeeni jaoks"
#: plinth/modules/users/templates/users_passkeys.html:94
msgid "Added"
msgstr ""
#: plinth/modules/users/templates/users_passkeys.html:95
#, fuzzy
#| msgid "Create User"
msgid "Last Used"
msgstr "Lisa kasutaja"
msgstr "Viimati kasutatud"
#: plinth/modules/users/templates/users_passkeys.html:126
msgid "No passkeys added to user account."
@ -8760,10 +8748,8 @@ msgid "You will need this passkey's device to add it back again."
msgstr ""
#: plinth/modules/users/templates/users_passkeys.html:152
#, fuzzy
#| msgid "Delete user"
msgid "Delete passkey"
msgstr "Kustuta kasutaja"
msgstr "Kustuta pääsuvõti"
#: plinth/modules/users/templates/users_passkeys.html:155
#: plinth/modules/users/templates/users_update.html:72
@ -8840,10 +8826,8 @@ msgid "Password changed successfully."
msgstr "Salasõna muutmine õnnestus."
#: plinth/modules/users/views.py:420
#, fuzzy
#| msgid "A library with this name already exists."
msgid "Passkey with that identifier already exists."
msgstr "Sellise nimega raamatukogu on juba olemas."
msgstr "Sellise tunnusega pääsuvõti on juba olemas."
#: plinth/modules/users/views.py:431
msgid "Edit Passkey"
@ -8877,10 +8861,8 @@ msgid "Invalid key."
msgstr "Vigane võti."
#: plinth/modules/wireguard/forms.py:63
#, fuzzy
#| msgid "IP address"
msgid "Not a valid IP address."
msgstr "IP-aadress"
msgstr "Pole korrektne IP-aadress."
#: plinth/modules/wireguard/forms.py:69
#: plinth/modules/wireguard/templates/wireguard.html:29
@ -8983,10 +8965,8 @@ msgid "Value"
msgstr ""
#: plinth/modules/wireguard/templates/wireguard.html:33
#, fuzzy
#| msgid "Endpoint"
msgid "Endpoint(s)"
msgstr "Otspunkt"
msgstr "Otspunkt(id)"
#: plinth/modules/wireguard/templates/wireguard.html:41
#, python-format
@ -9033,10 +9013,8 @@ msgid "Add Allowed Client"
msgstr ""
#: plinth/modules/wireguard/templates/wireguard.html:103
#, fuzzy
#| msgid "Password changed successfully."
msgid "WireGuard server not started yet."
msgstr "Salasõna muutmine õnnestus."
msgstr "WireGuardi server pole veel käivitatud."
#: plinth/modules/wireguard/templates/wireguard.html:107
#: plinth/modules/wireguard/templates/wireguard.html:109
@ -9072,20 +9050,16 @@ msgid "Add Connection to Server"
msgstr ""
#: plinth/modules/wireguard/templates/wireguard_add_client.html:21
#, fuzzy
#| msgid "IP address to use for client:"
msgid "IP address that will be assigned to this client"
msgstr "IP-aadress kasutamiseks kliendi jaoks:"
msgstr "IP-aadress, mis määratakse selle kliendi jaoks"
#: plinth/modules/wireguard/templates/wireguard_add_client.html:31
msgid "Add Client"
msgstr ""
#: plinth/modules/wireguard/templates/wireguard_auto_add_client.html:26
#, fuzzy
#| msgid "Privacy"
msgid "Private Key"
msgstr "Privaatsus"
msgstr "Privaatvõti"
#: plinth/modules/wireguard/templates/wireguard_auto_add_client.html:29
msgid "Click to reveal"
@ -9100,10 +9074,8 @@ msgid "Save the private key now. This page shows it only once!"
msgstr ""
#: plinth/modules/wireguard/templates/wireguard_auto_add_client.html:41
#, fuzzy
#| msgid "Configuration"
msgid "Client configuration file"
msgstr "Seadistused"
msgstr "Kliendi seadistustefail"
#: plinth/modules/wireguard/templates/wireguard_auto_add_client.html:43
msgid ""
@ -9112,10 +9084,8 @@ msgid ""
msgstr ""
#: plinth/modules/wireguard/templates/wireguard_auto_add_client.html:49
#, fuzzy
#| msgid "warning"
msgid "Warning:"
msgstr "hoiatus"
msgstr "Hoiatus:"
#: plinth/modules/wireguard/templates/wireguard_auto_add_client.html:50
msgid ""
@ -9284,10 +9254,8 @@ msgid "Server deleted."
msgstr ""
#: plinth/modules/wireguard/views.py:408
#, fuzzy
#| msgid "Password changed successfully."
msgid "WireGuard server started successfully."
msgstr "Salasõna muutmine õnnestus."
msgstr "WireGuardi serveri käivitamine õnnestus."
#: plinth/modules/wireguard/views.py:412
msgid "Failed to start WireGuard server: {}"
@ -9628,10 +9596,8 @@ msgid " System"
msgstr ""
#: plinth/templates/base.html:179 plinth/templates/base.html:180
#, fuzzy
#| msgid "Manage Passwords"
msgid "Manage passkeys"
msgstr "Halda salasõnu"
msgstr "Halda pääsuvõtmeid"
#: plinth/templates/base.html:186 plinth/templates/base.html:187
msgid "Change password"
@ -9658,10 +9624,8 @@ msgid "Add new app"
msgstr ""
#: plinth/templates/cards.html:48
#, fuzzy
#| msgid "Backup app before uninstall"
msgid "Available for install"
msgstr "Enne rakenduse eemaldamist palun tee varukoopia"
msgstr "Saadaval paigalduseks"
#: plinth/templates/clients-button.html:16
msgid "Launch web client"

View File

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: FreedomBox UI\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-07-29 02:26+0000\n"
"PO-Revision-Date: 2026-07-06 15:01+0000\n"
"PO-Revision-Date: 2026-08-11 10:51+0000\n"
"Last-Translator: Coucouf <coucouf@coucouf.fr>\n"
"Language-Team: French <https://hosted.weblate.org/projects/freedombox/"
"freedombox/fr/>\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 2026.7.1.dev0\n"
"X-Generator: Weblate 2026.9.dev0\n"
#: plinth/config.py:103
#, python-brace-format
@ -3029,7 +3029,7 @@ msgstr ""
#: plinth/modules/first_boot/__init__.py:47
msgid "First Boot"
msgstr ""
msgstr "Premier démarrage"
#: plinth/modules/first_boot/__init__.py:68
msgid "Setup complete! Next steps:"
@ -3053,19 +3053,15 @@ msgid "See next steps"
msgstr "Voir les prochaines étapes"
#: plinth/modules/first_boot/forms.py:14
#, fuzzy, python-brace-format
#| msgid ""
#| "Enter the secret generated during FreedomBox installation. This secret "
#| "can also be obtained by running the command \"sudo cat /var/lib/plinth/"
#| "firstboot-wizard-secret\" on your {box_name}"
#, python-brace-format
msgid ""
"Enter the secret generated during {box_name} installation. This secret can "
"be obtained by running the command \"sudo cat /var/lib/plinth/firstboot-"
"wizard-secret\" on your {box_name}"
msgstr ""
"Entrez le code secret généré durant l’installation de la FreedomBox. Il peut "
"également être obtenu en lançant la commande « sudo cat /var/lib/plinth/"
"firstboot-wizard-secret » sur votre {box_name}"
"Entrez le code secret généré durant l’installation de la {box_name}. Il peut "
"être obtenu en lançant la commande « sudo cat /var/lib/plinth/firstboot-"
"wizard-secret » sur votre {box_name}."
#: plinth/modules/first_boot/forms.py:19
msgid "Firstboot Wizard Secret"
@ -4777,10 +4773,15 @@ msgid ""
"game. It allows users to build and explore 3D worlds, interact with others, "
"and engage in various activities such as crafting, mining, and combat."
msgstr ""
"Luanti (précédemment nommé Minetest) est un jeu bac-à-sable de construction "
"de blocs multijoueur à monde infini. Il propose la construction et "
"l’exploration de mondes en 3D, l’interaction à plusieurs et la possibilité "
"de s’adonner à des activités telles que l’artisanat, l’extraction de "
"ressources et le combat."
#: plinth/modules/minetest/__init__.py:36
msgid "Luanti offers several educational benefits, including:"
msgstr ""
msgstr "Luanti a plusieurs intérêts éducatifs, notamment :"
#: plinth/modules/minetest/__init__.py:37
msgid ""
@ -4789,6 +4790,11 @@ msgid ""
"exploration.</li><li>Fostering social interaction and collaboration among "
"players.</li></ul>"
msgstr ""
"<ul><li>le développement de la représentation dans l’espace et des capacités "
"de résolution de problèmes ;</li><li>la stimulation de la créativité et de "
"l’expression personnelle au travers de la construction et de "
"l’exploration ;</li><li>l’incitation à la collaboration et aux interactions "
"sociales entres joueuses et joueurs.</li></ul>"
#: plinth/modules/minetest/__init__.py:43
#, python-brace-format
@ -4799,6 +4805,12 @@ msgid ""
"please refer to the official <a href=\"https://docs.luanti.org/\">Minetest "
"documentation</a> or online resources."
msgstr ""
"Pour commencer à jouer, installez le <a href=\"https://www.luanti.org/"
"downloads/\">client Luanti</a> sur vos appareils et connectez-vous au "
"serveur Luanti en utilisant l’IP de la {box_name} et le port part défaut "
"(30000). Pour plus d’informations, référez-vous à la <a href=\"https://"
"docs.luanti.org/\">documentation Luanti</a> officielle ou aux nombreuses "
"ressources disponibles en ligne."
#: plinth/modules/minetest/__init__.py:68 plinth/modules/minetest/manifest.py:9
msgid "Luanti"
@ -4814,7 +4826,7 @@ msgid ""
"instance of time."
msgstr ""
"Vous permet de modifier le nombre maximum de joueurs autorisés à se "
"connecter à minetest en même temps."
"connecter à Luanti en même temps."
#: plinth/modules/minetest/forms.py:19
msgid "Enable creative mode"
@ -11148,16 +11160,12 @@ msgid "Log in"
msgstr "S’identifier"
#: plinth/templates/cards.html:28
#, fuzzy
#| msgid "Add a new peer"
msgid "Add new app"
msgstr "Ajouter un nouveau pair"
msgstr "Ajouter une nouvelle appli"
#: plinth/templates/cards.html:48
#, fuzzy
#| msgid "Available Domains"
msgid "Available for install"
msgstr "Domaines disponibles"
msgstr "Disponibles à l’installation"
#: plinth/templates/clients-button.html:16
msgid "Launch web client"

View File

@ -9,6 +9,7 @@ import logging
import pathlib
import threading
from copy import deepcopy
from typing import Any
import psutil
from django.urls import reverse_lazy
@ -40,7 +41,7 @@ _description = [
logger = logging.Logger(__name__)
current_results = {}
current_results: dict[str, Any] = {}
results_lock = threading.Lock()

View File

@ -45,7 +45,6 @@ _description = [
'quality, privacy and legal reviews are done by the upstream '
'project and not by Debian/{box_name}. Updates are performed '
'following an independent cycle.'), box_name=_(cfg.box_name)),
format_lazy(_alert, _('Caution:'), _('This app is experimental.')),
]

View File

@ -17,7 +17,8 @@ class TestMatrixSynapseApp(functional.BaseAppTests):
diagnostics_delay = 1
@pytest.fixture(scope='class', autouse=True)
def fixture_setup(self, session_browser):
@classmethod
def fixture_setup(cls, session_browser):
"""Setup the app."""
functional.login(session_browser)
functional.domain_add(session_browser, 'mydomain.example')

View File

@ -21,7 +21,8 @@ class TestSambaApp(functional.BaseAppTests):
has_web = False
@pytest.fixture(scope='class', autouse=True)
def fixture_setup(self, session_browser):
@classmethod
def fixture_setup(cls, session_browser):
"""Setup the app."""
functional.login(session_browser)
functional.networks_set_firewall_zone(session_browser, 'internal')

View File

@ -3,6 +3,7 @@
import logging
import threading
from typing import Any
from plinth import cfg
from plinth.utils import import_from_gi
@ -40,7 +41,7 @@ _ERRORS: dict[str, str] = {
'Failed': 'org.freedesktop.UDisks2.Error.Failed',
}
_jobs = {}
_jobs: dict[str, Any] = {}
logger = logging.getLogger(__name__)

View File

@ -26,7 +26,6 @@ See: https://docs.djangoproject.com/en/dev/ref/settings/
"""
import django
from django.utils.translation import gettext_lazy as _
ALLOWED_HOSTS = ['*']
@ -240,9 +239,6 @@ TEMPLATES = [
TIME_ZONE = 'UTC'
if django.VERSION <= (4, 0):
USE_L10N = True
USE_TZ = True
# Overridden by configuration setting use_x_forwarded_host

View File

@ -837,12 +837,13 @@ class BaseAppTests:
install(session_browser, self.app_name)
@pytest.fixture(autouse=True, scope='class', name='disable_after_tests')
def fixture_disable_after_tests(self, session_browser):
@classmethod
def fixture_disable_after_tests(cls, session_browser):
"""Disable the app after running tests."""
yield
if self.disable_after_tests and is_installed(session_browser,
self.app_name):
app_disable(session_browser, self.app_name)
if cls.disable_after_tests and is_installed(session_browser,
cls.app_name):
app_disable(session_browser, cls.app_name)
@pytest.fixture(autouse=True, name='background')
def fixture_background(self, session_browser, disable_after_tests):

View File

@ -9,6 +9,12 @@ classifiers = [
"Environment :: No Input/Output (Daemon)",
"Environment :: Web Environment",
"Framework :: Django",
"Framework :: Django :: 5",
"Framework :: Django :: 5.0",
"Framework :: Django :: 5.1",
"Framework :: Django :: 5.2",
"Framework :: Django :: 6",
"Framework :: Django :: 6.0",
"Intended Audience :: End Users/Desktop",
"Natural Language :: English",
"Operating System :: POSIX :: Linux",