From 276893b3022665c08d923f2c56f3869b387f2d9a Mon Sep 17 00:00:00 2001 From: Thomas Vincent Date: Tue, 25 Feb 2020 22:36:20 +0000 Subject: [PATCH 01/41] Translated using Weblate (French) Currently translated at 94.6% (1197 of 1265 strings) --- plinth/locale/fr/LC_MESSAGES/django.po | 142 ++++++++++++------------- 1 file changed, 68 insertions(+), 74 deletions(-) diff --git a/plinth/locale/fr/LC_MESSAGES/django.po b/plinth/locale/fr/LC_MESSAGES/django.po index f67d612b2..a783c099e 100644 --- a/plinth/locale/fr/LC_MESSAGES/django.po +++ b/plinth/locale/fr/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: FreedomBox UI\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-02-24 19:12-0500\n" -"PO-Revision-Date: 2020-02-21 23:32+0000\n" +"PO-Revision-Date: 2020-02-26 23:32+0000\n" "Last-Translator: Thomas Vincent \n" "Language-Team: French \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 3.11.1\n" +"X-Generator: Weblate 4.0-dev\n" #: doc/dev/_build/html/_sources/tutorial/customizing.rst.txt:23 msgid "Custom Section" @@ -647,10 +647,8 @@ msgid "Enable Domain Name System Security Extensions" msgstr "Activer les extensions de sécurité DNS (DNSSEC)" #: plinth/modules/bind/templates/bind.html:11 -#, fuzzy -#| msgid "Server domain" msgid "Serving Domains" -msgstr "Domaine du serveur" +msgstr "Domaines servis" #: plinth/modules/bind/templates/bind.html:16 #: plinth/modules/ikiwiki/forms.py:12 @@ -660,27 +658,21 @@ msgid "Type" msgstr "Type" #: plinth/modules/bind/templates/bind.html:17 -#, fuzzy -#| msgid "Domain Name" msgid "Domain Names" -msgstr "Nom de domaine" +msgstr "Noms de domaine" #: plinth/modules/bind/templates/bind.html:18 -#, fuzzy -#| msgid "Service" msgid "Serving" -msgstr "Service" +msgstr "Servant" #: plinth/modules/bind/templates/bind.html:19 -#, fuzzy -#| msgid "IP address" msgid "IP addresses" -msgstr "Adresse IP" +msgstr "Adresses IP" #: plinth/modules/bind/templates/bind.html:35 #: plinth/modules/bind/templates/bind.html:37 msgid "Refresh IP address and domains" -msgstr "" +msgstr "Rafraîchir l’adresse IP et les domaines" #: plinth/modules/bind/views.py:73 plinth/modules/deluge/views.py:46 #: plinth/modules/dynamicdns/views.py:150 plinth/modules/openvpn/views.py:134 @@ -3580,7 +3572,7 @@ msgstr "Ouvert" #: plinth/modules/networks/forms.py:297 msgid "Choose your internet connection type" -msgstr "" +msgstr "Choisissez votre type de connexion à Internet" #: plinth/modules/networks/forms.py:301 msgid "" @@ -3592,6 +3584,14 @@ msgid "" "connectivity. If you have a public IP address but are unsure if it changes " "over time or not, it is safer to choose this option.

" msgstr "" +"J’ai une adresse IP publique pouvant changer avec le temps

Cela signifie que les appareils sur Internet peuvent vous joindre " +"quand vous êtes connecté à Internet. À chaque connexion avec votre " +"fournisseur d’accès à Internet (FAI), il se peut que vous ayez une adresse " +"IP différente, en particulier après un certain temps hors ligne. De nombreux " +"FAI proposent ce type de connectivité. Si vous avez une adresse IP publique " +"mais ne savez pas si celle-ci peut changer dans le temps, il est plus sûr de " +"choisir cette option.

" #: plinth/modules/networks/forms.py:313 #, python-brace-format @@ -3604,6 +3604,14 @@ msgid "" "but very few ISPs offer this. You may be able to get this service from your " "ISP by making an additional payment.

" msgstr "" +"J’ai une adresse IP publique ne pouvant pas changer avec le temps " +"(recommandé)

Cela signifie que les appareils sur " +"Internet peuvent vous joindre quand vous êtes connecté à Internet. À chaque " +"connexion avec votre fournisseur d’accès à Internet (FAI), vous avez " +"toujours la même adresse IP. Il s’agit de la situation la moins " +"problématique pour beaucoup des services de {box_name} mais très peu de FAI " +"proposent cela. Il se peut que vous puissiez en bénéficier contre un surcoût " +"auprès de votre FAI.

" #: plinth/modules/networks/forms.py:326 #, python-brace-format @@ -3616,20 +3624,21 @@ msgid "" "troublesome situation for hosting services at home. {box_name} provides many " "workaround solutions but each solution has some limitations.

" msgstr "" +"Je n’ai d’adresse IP publique

Cela signifie que les " +"appareils sur Internet ne peuvent pas vous joindre quand vous êtes " +"connecté à Internet. À chaque connexion avec votre fournisseur d’accès à " +"Internet (FAI), vous n’obtenez qu’une adresse IP utilisables dans vos " +"réseaux locaux. De nombreux FAI proposent ce type de connectivité. Il s’agit " +"de la situation la plus problématique pour héberger des services à domicile. " +"{box_name} fournit plusieurs solutions de contournement mais chaque solution " +"a des limitations.

" #: plinth/modules/networks/forms.py:351 msgid "Preferred router configuration" msgstr "Configuration préférée de routeur" #: plinth/modules/networks/forms.py:356 -#, fuzzy, python-brace-format -#| msgid "" -#| "Use DMZ feature to forward all traffic

Most " -#| "routers provide a configuration setting called DMZ. This will allow the " -#| "router to forward all incoming traffic from the internet to a single IP " -#| "address such as the {box_name}'s address. First remember to configure a " -#| "static local IP address for your {box_name} in your router's " -#| "configuration.

" +#, python-brace-format msgid "" "Use DMZ feature to forward all traffic (recommended)

Most routers provide a configuration setting called DMZ. This will allow " @@ -3638,10 +3647,10 @@ msgid "" "static local IP address for your {box_name} in your router's configuration." msgstr "" -"Utilisez la fonction de réseau isolé (DMZ) pour transférer tout le trafic

La plupart des routeurs proposent une configuration " -"appelée DMZ. Celle-ci vous permet de transférer tout le trafic entrant " -"depuis Internet vers une adresse IP unique telle que l’adresse de " +"Utilisez la fonction de réseau isolé (DMZ) pour transférer tout le trafic " +"(recommandé)

La plupart des routeurs proposent une " +"configuration appelée DMZ. Celle-ci vous permet de transférer tout le trafic " +"entrant depuis Internet vers une adresse IP unique telle que l’adresse IP de " "{box_name}. Pensez d’abord à configurer une adresse IP locale statique pour " "votre {box_name} dans la configuration de votre router.

" @@ -3764,10 +3773,8 @@ msgid "Router configuration type saved." msgstr "Type de configuration de routeur enregistré." #: plinth/modules/networks/networks.py:474 -#, fuzzy -#| msgid "Router configuration type saved." msgid "Internet connection type saved." -msgstr "Type de configuration de routeur enregistré." +msgstr "Type de connexion à Internet enregistré." #: plinth/modules/networks/templates/connection_show.html:28 msgid "Edit connection" @@ -4021,26 +4028,21 @@ msgstr "Créer..." #: plinth/modules/networks/templates/internet_connectivity_content.html:10 msgid "What Type Of Internet Connection Do You Have?" -msgstr "" +msgstr "Quel type de connexion à Internet avez-vous ?" #: plinth/modules/networks/templates/internet_connectivity_content.html:16 -#, fuzzy -#| msgid "" -#| "The following best describes how your %(box_name)s is connected in your " -#| "network. This information is used only to suggest necessary configuration " -#| "actions." msgid "" "Select an option that best describes the type of Internet connection. This " "information is used only to guide you with further setup." msgstr "" -"Les informations suivantes décrivent au mieux comment votre %(box_name)s est " -"connectée à votre réseau. Ces informations ne sont utilisées que pour " -"suggérer des actions de configuration nécessaires." +"Choisissez une option qui décrit au mieux le type de connexion à Internet. " +"Cette information n’est utilisée que pour vous guider avec la configuration " +"qui suit." #: plinth/modules/networks/templates/internet_connectivity_firstboot.html:18 #: plinth/modules/networks/templates/router_configuration_firstboot.html:18 msgid "Skip this step" -msgstr "" +msgstr "Passer cette étape" #: plinth/modules/networks/templates/internet_connectivity_firstboot.html:19 #: plinth/modules/networks/templates/router_configuration_firstboot.html:19 @@ -4048,37 +4050,31 @@ msgid "Next" msgstr "Suivant" #: plinth/modules/networks/templates/internet_connectivity_main.html:9 -#, fuzzy -#| msgid "Connection Type" msgid "Your Internet Connection Type" -msgstr "Type de Connexion" +msgstr "Votre Type de Connexion à Internet" #: plinth/modules/networks/templates/internet_connectivity_main.html:14 -#, fuzzy -#| msgid "" -#| "The following best describes how your %(box_name)s is connected in your " -#| "network. This information is used only to suggest necessary configuration " -#| "actions." msgid "" "The following best describes the type of Internet connection provided by " "your ISP. This information is only used to suggest you necessary " "configuration actions." msgstr "" -"Les informations suivantes décrivent au mieux comment votre %(box_name)s est " -"connectée à votre réseau. Ces informations ne sont utilisées que pour " -"suggérer des actions de configuration nécessaires." +"Les informations suivantes décrivent au mieux le type de connexion à " +"Internet fourni par votre FAI. Ces informations ne sont utilisées que pour " +"vous suggérer des actions de configuration nécessaires." #: plinth/modules/networks/templates/internet_connectivity_main.html:23 msgid "My ISP provides a public IP address that does not change over time." msgstr "" +"Mon FAI fournit une adresse IP publique qui ne change pas avec le temps." #: plinth/modules/networks/templates/internet_connectivity_main.html:27 msgid "My ISP provides a public IP address that may change over time." -msgstr "" +msgstr "Mon FAI fournit une adresse IP publique qui peut changer avec le temps." #: plinth/modules/networks/templates/internet_connectivity_main.html:31 msgid "My ISP does not provide a public IP address." -msgstr "" +msgstr "Mon FAI ne fournit pas d’adresse IP publique." #: plinth/modules/networks/templates/internet_connectivity_main.html:37 #: plinth/modules/networks/templates/router_configuration_main.html:29 @@ -4152,15 +4148,12 @@ msgstr "" "suggérer des actions de configuration nécessaires." #: plinth/modules/networks/templates/router_configuration_main.html:23 -#, fuzzy, python-format -#| msgid "" -#| "Your %(box_name)s gets its internet from your Router via WiFi or Ethernet " -#| "cable. This is a typical home setup." +#, python-format msgid "" "Your %(box_name)s gets its Internet from your Router via Wi-Fi or Ethernet " "cable. This is a typical home setup." msgstr "" -"Votre %(box_name)s tire son accès à Internet de votre routeur grâce au WiFi " +"Votre %(box_name)s tire son accès à Internet de votre routeur grâce au Wi-Fi " "ou à un câble Ethernet. Il s’agit de la configuration domestique classique." #: plinth/modules/openvpn/__init__.py:26 @@ -4202,10 +4195,8 @@ msgid "Enable OpenVPN server" msgstr "Activer le serveur OpenVPN" #: plinth/modules/openvpn/manifest.py:48 -#, fuzzy -#| msgid "TunnelBlick" msgid "Tunnelblick" -msgstr "TunnelBlick" +msgstr "Tunnelblick" #: plinth/modules/openvpn/templates/openvpn.html:27 #, python-format @@ -5156,10 +5147,10 @@ msgid "" "sandboxing features are in use. Sandboxing mitigates the impact of a " "potentially compromised app to the rest of the system." msgstr "" -"Pour les applications fournissant des services, la colonne \"Bac à sable\" " -"montre si les fonctionnalités d’isolation (sandboxing) sont utilisées. " -"L’isolation limite l’impact sur le reste du système d’une application " -"potentiellement compromise." +"Pour les applications fournissant des services, la colonne « Isolé » montre " +"si les fonctionnalités d’isolation (sandboxing) sont utilisées. L’isolation " +"limite l’impact sur le reste du système d’une application potentiellement " +"compromise." #: plinth/modules/security/templates/security_report.html:31 msgid "" @@ -5167,6 +5158,9 @@ msgid "" "from the rest of the system. It is only displayed while the service is " "running." msgstr "" +"« Couverture de l’isolation » est un score indiquant avec quelle efficacité " +"le service est isolé du reste du système. Il n’est affiché que lorsque le " +"service est lancé." #: plinth/modules/security/templates/security_report.html:40 msgid "App Name" @@ -5182,13 +5176,11 @@ msgstr "Anciennes failles" #: plinth/modules/security/templates/security_report.html:43 msgid "Sandboxed" -msgstr "Bac à sable" +msgstr "Isolé" #: plinth/modules/security/templates/security_report.html:44 -#, fuzzy -#| msgid "Sandboxed" msgid "Sandbox Coverage" -msgstr "Bac à sable" +msgstr "Couverture de l’isolation" #: plinth/modules/security/templates/security_report.html:55 msgid "N/A" @@ -6325,11 +6317,13 @@ msgid "" "%(box_name)s has been updated to version %(version)s. See the release announcement." msgstr "" +"%(box_name)s a été mis à jour vers la version %(version)s. Consultez l’annonce de publication." #: plinth/modules/upgrades/templates/upgrades-new-release.html:22 #: plinth/templates/notifications.html:44 msgid "Dismiss" -msgstr "" +msgstr "Ignorer" #: plinth/modules/upgrades/templates/upgrades.html:30 msgid "Update now" @@ -6427,15 +6421,15 @@ msgid "Username is taken or is reserved." msgstr "Le nom d'utilisateur est déjà pris ou est réservé." #: plinth/modules/users/forms.py:72 -#, fuzzy -#| msgid "Invalid server name" msgid "Enter a valid username." -msgstr "Nom de serveur invalide" +msgstr "Entrez un nom d’utilisateur valide." #: plinth/modules/users/forms.py:78 msgid "" "Required. 150 characters or fewer. English letters, digits and @/./-/_ only." msgstr "" +"Requis. 150 caractères ou moins. Lettres anglaises, chiffres et @/./-/_ " +"seulement." #: plinth/modules/users/forms.py:91 plinth/modules/users/forms.py:207 msgid "Permissions" From b5f6821fd77d290c02298e1807cefab3cce4440a Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Mon, 24 Feb 2020 19:37:18 -0500 Subject: [PATCH 02/41] networks: Fixes for networks wizards - Make first wizard steps for router configuration and Internet connection type private. Since they run after the admin user page, the steps can run for logged in users. - Add option to the Internet connection type wizard, to let the user say that they don't know the type. This allows them to have a stress-free first setup experience. The option can act as if they have don't have public IP address at all. This is an extension of the proposed user experience. - Implement class based views for simplicity. - Update various IDs for consistency (even though other IDs in the networks module don't conform). - Iron out inconsistent terminology. Setup vs Configuration, Help vs. Wizard, etc. Tests performed: - Run first boot wizard from the beginning. Notice that both the wizard steps appear properly after the user login step (without permission denied problems). When not logged in, accessing the wizard steps with URL should redirect to login page. - During first boot wizard, select 'Skip this step' in both the steps after selecting non-default options. Values set should be default options as confirmed from networks page. - During first boot wizard, select non-default values, the values should be set properly as confirmed from networks page. - From the networks page select each value of the wizard. The option should get saved properly. - In case of Internet connection type, when the wizard values changes, the networks page should reflect the value properly. This should also show properly after skipping the step during first boot. - During first boot, the default value for Internet connection type should be 'I don't know' and router configuration should be 'Not configured'. Signed-off-by: Sunil Mohan Adapa Reviewed-by: Nektarios Katakis --- plinth/modules/networks/__init__.py | 4 +- plinth/modules/networks/forms.py | 7 +- plinth/modules/networks/networks.py | 137 ++++++++---------- .../internet_connectivity_firstboot.html | 6 +- .../templates/internet_connectivity_main.html | 8 +- .../router_configuration_firstboot.html | 6 +- .../templates/router_configuration_main.html | 2 +- plinth/modules/networks/urls.py | 22 ++- 8 files changed, 97 insertions(+), 95 deletions(-) diff --git a/plinth/modules/networks/__init__.py b/plinth/modules/networks/__init__.py index 34139ed7f..74005b15e 100644 --- a/plinth/modules/networks/__init__.py +++ b/plinth/modules/networks/__init__.py @@ -21,12 +21,12 @@ managed_packages = ['network-manager', 'batctl'] first_boot_steps = [ { 'id': 'internet_connectivity_type_wizard', - 'url': 'networks:firstboot_internet_connection_type', + 'url': 'networks:internet-connection-type-first-boot', 'order': 3, }, { 'id': 'router_setup_wizard', - 'url': 'networks:firstboot_router_setup', + 'url': 'networks:router-configuration-first-boot', 'order': 4, }, ] diff --git a/plinth/modules/networks/forms.py b/plinth/modules/networks/forms.py index 0203838e5..2443d7c73 100644 --- a/plinth/modules/networks/forms.py +++ b/plinth/modules/networks/forms.py @@ -334,13 +334,18 @@ class InternetConnectionTypeForm(forms.Form): '{box_name} provides many workaround solutions but each ' 'solution has some limitations.

'), box_name=cfg.box_name, allow_markup=True)), + ('unknown', + format_lazy( + _('I do not know the type of connection my ISP provides ' + '

You will be suggested the most ' + 'conservative actions.

'), allow_markup=True)), ], required=True, widget=forms.RadioSelect, ) -class RouterConfigurationWizardForm(forms.Form): +class RouterConfigurationForm(forms.Form): """Form to suggest how to configure a router. Suggest depending on wan connectivity/specific setup. The choice will diff --git a/plinth/modules/networks/networks.py b/plinth/modules/networks/networks.py index a40266ea4..0616fddd7 100644 --- a/plinth/modules/networks/networks.py +++ b/plinth/modules/networks/networks.py @@ -8,13 +8,14 @@ from django.template.response import TemplateResponse from django.urls import reverse_lazy from django.utils.translation import ugettext as _ from django.views.decorators.http import require_POST +from django.views.generic.edit import FormView from plinth import kvstore, network from plinth.modules import first_boot, networks from .forms import (ConnectionTypeSelectForm, EthernetForm, GenericForm, InternetConnectionTypeForm, PPPoEForm, - RouterConfigurationWizardForm, WifiForm) + RouterConfigurationForm, WifiForm) logger = logging.getLogger(__name__) @@ -24,7 +25,7 @@ def index(request): connections = network.get_connection_list() internet_connection_type = kvstore.get_default( - networks.INTERNET_CONNECTION_TYPE_KEY, None) + networks.INTERNET_CONNECTION_TYPE_KEY, 'unknown') return TemplateResponse( request, 'networks_configuration.html', { 'app_id': 'networks', @@ -405,89 +406,79 @@ def delete(request, uuid): }) -def router_configuration_help_page(request): - """Show the router configuration wizard page/form. +class RouterConfigurationView(FormView): + """View for router configuration form.""" + template_name = 'router_configuration_update.html' + form_class = RouterConfigurationForm + success_url = reverse_lazy('networks:index') - Used both for fistboot step and same networks page. - - """ - is_firstboot = True \ - if 'firstboot' in request.build_absolute_uri() else False - - if request.method == 'POST' and request.POST['router_config']: - form = RouterConfigurationWizardForm(request.POST) - if form.is_valid(): - logger.info('Updating router configuration setup with value: %s' % - request.POST['router_config']) - kvstore.set(networks.ROUTER_CONFIGURATION_TYPE_KEY, - request.POST['router_config']) - if is_firstboot: - resp = reverse_lazy(first_boot.next_step()) - else: - resp = reverse_lazy('networks:index') - messages.success(request, _('Router configuration type saved.')) - - return redirect(resp) - else: - html = 'router_configuration_update.html' - initial = { + def get_initial(self): + """Return initial data for the form.""" + return { 'router_config': kvstore.get_default(networks.ROUTER_CONFIGURATION_TYPE_KEY, - 'not_configured'), + 'not_configured') } - template_kwargs = { - 'form': RouterConfigurationWizardForm(initial=initial), - } - if is_firstboot: - html = 'router_configuration_firstboot.html' - # mark step done on firstboot visit to get the next_step - first_boot.mark_step_done('router_setup_wizard') - template_kwargs.update({ - 'first_boot_next_step': reverse_lazy(first_boot.next_step()), - }) - - return TemplateResponse(request, html, template_kwargs) + def form_valid(self, form): + """Save value to DB and redirect.""" + type_ = form.cleaned_data['router_config'] + logger.info('Updating router configuration: %s', type_) + kvstore.set(networks.ROUTER_CONFIGURATION_TYPE_KEY, type_) + return super().form_valid(form) -def internet_connection_type_help_page(request): - """Show the internet connection type page. +class RouterConfigurationFirstBootView(RouterConfigurationView): + """View for router configuration form during first wizard.""" + template_name = 'router_configuration_firstboot.html' - Used for first boot step and networks page. + def get_success_url(self): + """Return the next wizard step after this one.""" + return reverse_lazy(first_boot.next_step()) - """ - is_firstboot = True \ - if 'firstboot' in request.build_absolute_uri() else False + def form_valid(self, form): + """Mark the first wizard step as done, save value and redirect.""" + first_boot.mark_step_done('router_setup_wizard') + if 'skip' in form.data: + return FormView.form_valid(self, form) - if request.method == 'POST' and request.POST['internet_connection_type']: - form = InternetConnectionTypeForm(request.POST) - if form.is_valid(): - logger.info('Updating internet connectivity type with value: %s' % - request.POST['internet_connection_type']) - kvstore.set( - networks.INTERNET_CONNECTION_TYPE_KEY, - request.POST['internet_connection_type'], - ) - if is_firstboot: - return redirect(reverse_lazy(first_boot.next_step())) - else: - messages.success(request, _('Internet connection type saved.')) - return redirect(reverse_lazy('networks:index')) - else: - html = 'internet_connectivity_type.html' - initial = { + return super().form_valid(form) + + +class InternetConnectionTypeView(FormView): + """View for Internet connection type form.""" + template_name = 'internet_connectivity_type.html' + form_class = InternetConnectionTypeForm + success_url = reverse_lazy('networks:index') + + def get_initial(self): + """Return initial data for the form.""" + return { 'internet_connection_type': kvstore.get_default(networks.INTERNET_CONNECTION_TYPE_KEY, - None) + 'unknown') } - template_kwargs = {'form': InternetConnectionTypeForm(initial=initial)} - if is_firstboot: - html = 'internet_connectivity_firstboot.html' - # mark step done on firstboot visit to get the next_step - first_boot.mark_step_done('internet_connectivity_type_wizard') - template_kwargs.update({ - 'first_boot_next_step': reverse_lazy(first_boot.next_step()), - }) + def form_valid(self, form): + """Save value to DB and redirect.""" + type_ = form.cleaned_data['internet_connection_type'] + logger.info('Updating internet connectivity type: %s', type_) + kvstore.set(networks.INTERNET_CONNECTION_TYPE_KEY, type_) + return super().form_valid(form) - return TemplateResponse(request, html, template_kwargs) + +class InternetConnectionTypeFirstBootView(InternetConnectionTypeView): + """View to show Internet connection type form during first wizard.""" + template_name = 'internet_connectivity_firstboot.html' + + def get_success_url(self): + """Return the next wizard step after this one.""" + return reverse_lazy(first_boot.next_step()) + + def form_valid(self, form): + """Mark the first wizard step as done, save value and redirect.""" + first_boot.mark_step_done('internet_connectivity_type_wizard') + if 'skip' in form.data: + return FormView.form_valid(self, form) + + return super().form_valid(form) diff --git a/plinth/modules/networks/templates/internet_connectivity_firstboot.html b/plinth/modules/networks/templates/internet_connectivity_firstboot.html index 04c14e38e..6bd240144 100644 --- a/plinth/modules/networks/templates/internet_connectivity_firstboot.html +++ b/plinth/modules/networks/templates/internet_connectivity_firstboot.html @@ -15,7 +15,9 @@ {{ form|bootstrap }} - {% trans "Skip this step" %} - + + {% endblock %} diff --git a/plinth/modules/networks/templates/internet_connectivity_main.html b/plinth/modules/networks/templates/internet_connectivity_main.html index 25b30d5bd..ae6c23f0c 100644 --- a/plinth/modules/networks/templates/internet_connectivity_main.html +++ b/plinth/modules/networks/templates/internet_connectivity_main.html @@ -27,12 +27,16 @@ {% blocktrans trimmed %} My ISP provides a public IP address that may change over time. {% endblocktrans %} - {% else %} + {% elif internet_connectivity_type == "private_ip" %} {% blocktrans trimmed %} My ISP does not provide a public IP address. {% endblocktrans %} + {% else %} + {% blocktrans trimmed %} + I do not know the type of connection my ISP provides. + {% endblocktrans %} {% endif %} - {% trans 'Update...' %} diff --git a/plinth/modules/networks/templates/router_configuration_firstboot.html b/plinth/modules/networks/templates/router_configuration_firstboot.html index 81cfd8c8d..74877e993 100644 --- a/plinth/modules/networks/templates/router_configuration_firstboot.html +++ b/plinth/modules/networks/templates/router_configuration_firstboot.html @@ -15,8 +15,10 @@ {{ form|bootstrap }} - {% trans "Skip this step" %} - + + {% endblock %} diff --git a/plinth/modules/networks/templates/router_configuration_main.html b/plinth/modules/networks/templates/router_configuration_main.html index c3d109fba..b8c4369ed 100644 --- a/plinth/modules/networks/templates/router_configuration_main.html +++ b/plinth/modules/networks/templates/router_configuration_main.html @@ -24,7 +24,7 @@ Your {{ box_name }} gets its Internet from your Router via Wi-Fi or Ethernet cable. This is a typical home setup. {% endblocktrans %} - {% trans 'Update...' %} diff --git a/plinth/modules/networks/urls.py b/plinth/modules/networks/urls.py index 872c3a02d..637ca3f7f 100644 --- a/plinth/modules/networks/urls.py +++ b/plinth/modules/networks/urls.py @@ -4,7 +4,6 @@ URLs for the Network module """ from django.conf.urls import url -from stronghold.decorators import public from . import networks as views @@ -27,16 +26,15 @@ urlpatterns = [ r'(?P[^/]+)/)?$', views.add_wifi, name='add_wifi'), url(r'^sys/networks/(?P[\w.@+-]+)/delete/$', views.delete, name='delete'), - url(r'^sys/networks/router-setup-guide/$', - views.router_configuration_help_page, - name='router_setup'), - url(r'^sys/networks/firstboot/router_setup/$', - public(views.router_configuration_help_page), - name='firstboot_router_setup'), + url(r'^sys/networks/router-configuration/$', + views.RouterConfigurationView.as_view(), name='router-configuration'), + url(r'^sys/networks/firstboot/router-configuration/$', + views.RouterConfigurationFirstBootView.as_view(), + name='router-configuration-first-boot'), url(r'^sys/networks/internet-connection-type/$', - views.internet_connection_type_help_page, - name='internet_connection_type_setup'), - url(r'^sys/networks/firstboot/internet_connection_type/$', - public(views.internet_connection_type_help_page), - name='firstboot_internet_connection_type'), + views.InternetConnectionTypeView.as_view(), + name='internet-connection-type'), + url(r'^sys/networks/firstboot/internet-connection-type/$', + views.InternetConnectionTypeFirstBootView.as_view(), + name='internet-connection-type-first-boot'), ] From a0b565519631c4b955cbd23f09da5d1bfd9d7a6e Mon Sep 17 00:00:00 2001 From: Joseph Nuthalapati Date: Sat, 29 Feb 2020 12:46:23 +0000 Subject: [PATCH 03/41] Translated using Weblate (Telugu) Currently translated at 64.6% (818 of 1265 strings) --- plinth/locale/te/LC_MESSAGES/django.po | 84 +++++++++++++++----------- 1 file changed, 49 insertions(+), 35 deletions(-) diff --git a/plinth/locale/te/LC_MESSAGES/django.po b/plinth/locale/te/LC_MESSAGES/django.po index b8280f50d..72de14cfb 100644 --- a/plinth/locale/te/LC_MESSAGES/django.po +++ b/plinth/locale/te/LC_MESSAGES/django.po @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: FreedomBox UI\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-02-24 19:12-0500\n" -"PO-Revision-Date: 2020-02-10 05:50+0000\n" +"PO-Revision-Date: 2020-03-01 14:32+0000\n" "Last-Translator: Joseph Nuthalapati \n" "Language-Team: Telugu \n" @@ -19,7 +19,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 3.11-dev\n" +"X-Generator: Weblate 4.0-dev\n" #: doc/dev/_build/html/_sources/tutorial/customizing.rst.txt:23 #, fuzzy @@ -265,6 +265,8 @@ msgid "" "Password of the SSH Server.
SSH key-based authentication is not yet " "possible." msgstr "" +"SSH సర్వర్ యొక్క పాస్వర్డ్.
SSH కీ-ఆధారిత ప్రామాణీకరణ ఇంకా సాధ్యం " +"కాదు." #: plinth/modules/backups/forms.py:209 msgid "Remote backup repository already exists." @@ -272,7 +274,7 @@ msgstr "" #: plinth/modules/backups/forms.py:215 msgid "Select verified SSH public key" -msgstr "" +msgstr "ధృవీకరించబడిన SSH పబ్లిక్ కీని ఎంచుకోండి" #: plinth/modules/backups/repository.py:33 msgid "" @@ -288,7 +290,7 @@ msgstr "అనుసంధాన రకం" #: plinth/modules/backups/repository.py:47 msgid "Repository not found" -msgstr "" +msgstr "రిపోజిటరీ దొరకలేదు" #: plinth/modules/backups/repository.py:52 msgid "Incorrect encryption passphrase" @@ -296,15 +298,15 @@ msgstr "" #: plinth/modules/backups/repository.py:57 msgid "SSH access denied" -msgstr "" +msgstr "SSH యాక్సెస్ నిరాకరించబడింది" #: plinth/modules/backups/repository.py:63 msgid "Repository path is neither empty nor is an existing backups repository." -msgstr "" +msgstr "రిపోజిటరీ మార్గం ఖాళీగా లేదు లేదా ఇప్పటికే ఉన్న బ్యాకప్ రిపోజిటరీ." #: plinth/modules/backups/repository.py:137 msgid "Existing repository is not encrypted." -msgstr "" +msgstr "ఇప్పటికే ఉన్న రిపోజిటరీ గుప్తీకరించబడలేదు." #: plinth/modules/backups/repository.py:322 #, fuzzy, python-brace-format @@ -420,7 +422,7 @@ msgstr "సమర్పించు" #: plinth/modules/backups/templates/backups_repository_remove.html:13 msgid "Are you sure that you want to remove this repository?" -msgstr "" +msgstr "మీరు ఈ రిపోజిటరీని ఖచ్చితంగా తొలగించాలనుకుంటున్నారా?" #: plinth/modules/backups/templates/backups_repository_remove.html:19 msgid "" @@ -442,8 +444,6 @@ msgstr "%(name)s తొలగించు" #: plinth/modules/backups/templates/backups_restore.html:28 #: plinth/modules/backups/views.py:154 -#, fuzzy -#| msgid "reStore" msgid "Restore" msgstr "పునరుద్ధరించు" @@ -476,10 +476,8 @@ msgid "" msgstr "" #: plinth/modules/backups/templates/backups_upload.html:41 -#, fuzzy -#| msgid "Download my profile" msgid "Upload file" -msgstr "ఫైలు ఎగుమతించండి" +msgstr "ఫైలు ఎగుమతి చేయండి" #: plinth/modules/backups/templates/verify_ssh_hostkey.html:18 #, python-format @@ -543,7 +541,7 @@ msgstr "అప్‌లోడ్ చేసిన ఫైల్ నుండి #: plinth/modules/backups/views.py:234 msgid "No additional disks available to add a repository." -msgstr "" +msgstr "రిపోజిటరీని జోడించడానికి అదనపు డిస్కులు అందుబాటులో లేవు." #: plinth/modules/backups/views.py:242 #, fuzzy @@ -553,7 +551,7 @@ msgstr "స్నాప్షాట్‌ని సృష్టించు" #: plinth/modules/backups/views.py:269 msgid "Create remote backup repository" -msgstr "" +msgstr "రిమోట్ బ్యాకప్ రిపోజిటరీని సృష్టించండి" #: plinth/modules/backups/views.py:288 #, fuzzy @@ -563,23 +561,23 @@ msgstr "కొత్త పరిచయకర్తని జోడించం #: plinth/modules/backups/views.py:310 msgid "Verify SSH hostkey" -msgstr "" +msgstr "SSH హోస్ట్‌కీని ధృవీకరించండి" #: plinth/modules/backups/views.py:336 msgid "SSH host already verified." -msgstr "" +msgstr "SSH హోస్ట్ ఇప్పటికే ధృవీకరించబడింది." #: plinth/modules/backups/views.py:346 msgid "SSH host verified." -msgstr "" +msgstr "SSH హోస్ట్ ధృవీకరించబడింది." #: plinth/modules/backups/views.py:360 msgid "SSH host public key could not be verified." -msgstr "" +msgstr "SSH హోస్ట్ పబ్లిక్ కీని ధృవీకరించడం సాధ్యం కాలేదు." #: plinth/modules/backups/views.py:362 msgid "Authentication to remote server failed." -msgstr "" +msgstr "రిమోట్ సర్వర్‌కు ప్రామాణీకరణ విఫలమైంది." #: plinth/modules/backups/views.py:364 #, fuzzy @@ -589,23 +587,23 @@ msgstr "అనువర్తనం స్థాపించుటలో దో #: plinth/modules/backups/views.py:375 msgid "Repository removed." -msgstr "" +msgstr "రిపోజిటరీ తొలగించబడింది." #: plinth/modules/backups/views.py:389 msgid "Remove Repository" -msgstr "" +msgstr "రిపోజిటరీని తొలగించండి" #: plinth/modules/backups/views.py:398 msgid "Repository removed. Backups were not deleted." -msgstr "" +msgstr "రిపోజిటరీ తొలగించబడింది. బ్యాకప్‌లు తొలగించబడలేదు." #: plinth/modules/backups/views.py:408 msgid "Unmounting failed!" -msgstr "" +msgstr "అన్‌మౌంటింగ్ విఫలమైంది!" #: plinth/modules/backups/views.py:423 plinth/modules/backups/views.py:427 msgid "Mounting failed" -msgstr "" +msgstr "మౌంటింగ్ విఫలమైంది" #: plinth/modules/bind/__init__.py:29 msgid "" @@ -684,7 +682,7 @@ msgstr "IP చిరునామా" #: plinth/modules/bind/templates/bind.html:35 #: plinth/modules/bind/templates/bind.html:37 msgid "Refresh IP address and domains" -msgstr "" +msgstr "IP చిరునామా మరియు డొమైన్‌లను రిఫ్రెష్ చేయండి" #: plinth/modules/bind/views.py:73 plinth/modules/deluge/views.py:46 #: plinth/modules/dynamicdns/views.py:150 plinth/modules/openvpn/views.py:134 @@ -1721,11 +1719,11 @@ msgstr "" #: plinth/modules/gitweb/forms.py:69 plinth/modules/gitweb/forms.py:73 msgid "Optional, for displaying on Gitweb." -msgstr "" +msgstr "ఐచ్ఛికం, గిట్‌వెబ్‌లో ప్రదర్శించడానికి." #: plinth/modules/gitweb/forms.py:71 msgid "Repository's owner name" -msgstr "" +msgstr "రిపోజిటరీ యొక్క యజమాని పేరు" #: plinth/modules/gitweb/forms.py:76 #, fuzzy @@ -1736,6 +1734,8 @@ msgstr "వినియోగదారుని సృష్టించు" #: plinth/modules/gitweb/forms.py:77 msgid "Allow only authorized users to access this repository." msgstr "" +"ఈ రిపోజిటరీని యాక్సెస్ చేయడానికి అధికారం ఉన్న వినియోగదారులను మాత్రమే " +"అనుమతించండి." #: plinth/modules/gitweb/forms.py:98 plinth/modules/gitweb/forms.py:130 #, fuzzy @@ -1758,7 +1758,7 @@ msgstr "ప్రత్యేకంగా ఒక వాటాను గుర్ #: plinth/modules/gitweb/manifest.py:21 msgid "Git" -msgstr "" +msgstr "గిట్" #: plinth/modules/gitweb/templates/gitweb_configure.html:31 #, fuzzy @@ -1815,7 +1815,7 @@ msgstr "%(name)s తొలగించు" #: plinth/modules/gitweb/views.py:45 msgid "Repository created." -msgstr "" +msgstr "రిపోజిటరీ సృష్టించబడింది." #: plinth/modules/gitweb/views.py:67 #, fuzzy @@ -1825,7 +1825,7 @@ msgstr "అక్రుతీకరణలో ఒక పొరపాటు జర #: plinth/modules/gitweb/views.py:80 msgid "Repository edited." -msgstr "" +msgstr "రిపోజిటరీ సవరించబడింది." #: plinth/modules/gitweb/views.py:85 #, fuzzy @@ -1862,7 +1862,7 @@ msgstr "కరదీపిక" #: plinth/modules/help/templates/help_support.html:9 #: plinth/templates/help-menu.html:27 plinth/templates/help-menu.html:28 msgid "Get Support" -msgstr "" +msgstr "సహాయం పొందు" #: plinth/modules/help/__init__.py:41 plinth/modules/help/help.py:37 #: plinth/modules/help/templates/help_feedback.html:9 @@ -1994,6 +1994,11 @@ msgid "" "into your language, hosting hackathons or install fests, and by spreading " "the word." msgstr "" +"మీరు కోడ్ రాయడం, దోషాలను పరీక్షించడం మరియు నివేదించడం, క్రొత్త వినియోగ కేసులు" +" మరియు అనువర్తనాలను చర్చించడం, లోగోలు మరియు కళాకృతుల రూపకల్పన, మీ తోటి " +"వినియోగదారులకు మద్దతు ఇవ్వడం, ఫ్రీడమ్‌బాక్స్ మరియు దాని అనువర్తనాలను మీ " +"భాషలోకి అనువదించడం, హాకథాన్‌లను హోస్ట్ చేయడం లేదా ఫెస్ట్‌లను ఇన్‌స్టాల్ చేయడం" +" ద్వారా మరియు వ్యాప్తి చేయడం ద్వారా మీరు సహకరించవచ్చు." #: plinth/modules/help/templates/help_contribute.html:28 msgid "" @@ -2006,6 +2011,14 @@ msgid "" "throughout the world. The FreedomBox Foundation would not exist without its " "supporters." msgstr "" +"లాభాపేక్షలేని ఫ్రీడమ్‌బాక్స్ ఫౌండేషన్‌కు విరాళం ద్వారా మీరు ఆర్థికంగా" +" సహాయం చేయవచ్చు. ఫ్రీడమ్‌బాక్స్ ఫౌండేషన్ అనేది న్యూయార్క్ నగరంలో 501 (సి) (3)" +" హోదా కలిగిన లాభాపేక్షలేని సంస్థ, ఇది ఫ్రీడమ్‌బాక్స్‌కు మద్దతుగా ఉంది. ఇది " +"ప్రాజెక్ట్ కోసం సాంకేతిక మౌలిక సదుపాయాలు మరియు న్యాయ సేవలను అందిస్తుంది, " +"భాగస్వామ్యాలను అనుసరిస్తుంది మరియు ప్రపంచవ్యాప్తంగా ఫ్రీడమ్‌బాక్స్ వ్యాప్తి " +"కొరకు కృషి చేస్తుంది. ఫ్రీడమ్‌బాక్స్ ఫౌండేషన్ దాని మద్దతుదారులు లేకుండా " +"ఉండలేదు." #: plinth/modules/help/templates/help_contribute.html:42 #: plinth/modules/power/templates/power_restart.html:27 @@ -2025,6 +2038,9 @@ msgid "" "improve them on our discussion forum." msgstr "" +"మీకు ఇష్టమైన అనువర్తనాలు, కావలసిన లక్షణాలు మరియు వాటిని మేము ఎలా " +"మెరుగుపరచవచ్చో మా చర్చా వేదిక లో మాకు తెలియజేయండి." #: plinth/modules/help/templates/help_feedback.html:26 msgid "" @@ -3671,10 +3687,8 @@ msgid "Router configuration type saved." msgstr "టోర్ ఆకృతీకరణ నవీకరించబడుతుంది" #: plinth/modules/networks/networks.py:474 -#, fuzzy -#| msgid "Tor configuration is being updated" msgid "Internet connection type saved." -msgstr "టోర్ ఆకృతీకరణ నవీకరించబడుతుంది" +msgstr "ఇంటర్నెట్ కనెక్షన్ రకం సేవ్ చేయబడింది." #: plinth/modules/networks/templates/connection_show.html:28 msgid "Edit connection" From 03b4accefb53015fa8c46367db6cc8c05eafb6b9 Mon Sep 17 00:00:00 2001 From: Thomas Vincent Date: Fri, 28 Feb 2020 16:50:15 +0000 Subject: [PATCH 04/41] Translated using Weblate (French) Currently translated at 96.7% (1224 of 1265 strings) --- plinth/locale/fr/LC_MESSAGES/django.po | 103 ++++++++++++------------- 1 file changed, 48 insertions(+), 55 deletions(-) diff --git a/plinth/locale/fr/LC_MESSAGES/django.po b/plinth/locale/fr/LC_MESSAGES/django.po index a783c099e..ddeba3776 100644 --- a/plinth/locale/fr/LC_MESSAGES/django.po +++ b/plinth/locale/fr/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: FreedomBox UI\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-02-24 19:12-0500\n" -"PO-Revision-Date: 2020-02-26 23:32+0000\n" +"PO-Revision-Date: 2020-03-01 14:33+0000\n" "Last-Translator: Thomas Vincent \n" "Language-Team: French \n" @@ -3647,7 +3647,7 @@ msgid "" "static local IP address for your {box_name} in your router's configuration." msgstr "" -"Utilisez la fonction de réseau isolé (DMZ) pour transférer tout le trafic " +"Utiliser la fonction de réseau isolé (DMZ) pour transférer tout le trafic " "(recommandé)

La plupart des routeurs proposent une " "configuration appelée DMZ. Celle-ci vous permet de transférer tout le trafic " "entrant depuis Internet vers une adresse IP unique telle que l’adresse IP de " @@ -3665,6 +3665,14 @@ msgid "" "443 to work. Each of the other applications will suggest which port(s) need " "to be forwarded for that application to work.

" msgstr "" +"Transférer le trafic spécifique tel que requis par chaque application

Vous pourriez aussi choisir de transférer uniquement un " +"trafic spécifique vers votre {box_name}. Cela est idéal si vous avez d’" +"autres serveurs tels que {box_name} dans votre réseau ou si votre routeur ne " +"gère pas les fonctions de DMZ. Toutes les applications qui fournissent une " +"interface web ont besoin que vous transfériez le trafic des ports 80 et 443 " +"pour fonctionner. Les autres applications suggéreront quel(s) port(s) " +"transférer pour qu’elles fonctionnent.

" #: plinth/modules/networks/forms.py:382 msgid "" @@ -3672,6 +3680,10 @@ msgid "" "have not configured or are unable to configure the router currently and wish " "to be reminded later. Some of the other configuration steps may fail.

" msgstr "" +"Le routeur n’est pas configuré actuellement

" +"Choisissez ceci si vous n’avez pas configuré le routeur ou si vous n’en êtes " +"pas capable et souhaitez vous le rappeler plus tard. Certaines des autres " +"étapes de configuration pourraient échouer.

" #: plinth/modules/networks/networks.py:32 msgid "Network Connections" @@ -4092,7 +4104,7 @@ msgid "" "Your %(box_name)s gets its internet connection from your router via Wi-Fi or " "Ethernet cable. This is a typical home setup." msgstr "" -"Votre %(box_name)s tire son accès à Internet de votre routeur grâce au WiFi " +"Votre %(box_name)s tire son accès à Internet de votre routeur grâce au Wi-Fi " "ou à un câble Ethernet. Il s’agit de la configuration domestique classique." #: plinth/modules/networks/templates/router_configuration_content.html:23 @@ -4103,6 +4115,10 @@ msgid "" "configured to forward all traffic it receives so that %(box_name)s provides " "the services." msgstr "" +"Avec cette configuration, tout appareil sur Internet tentant de joindre " +"votre %(box_name)s devra passer par votre routeur. Le routeur devra être " +"configuré pour transférer tout le trafic qu’il reçoit afin que %(box_name)s " +"fournisse ses services." #: plinth/modules/networks/templates/router_configuration_content.html:32 msgid "" @@ -4110,10 +4126,14 @@ msgid "" "see options to overcome this limitation, choose 'no public address' option " "in Internet connection type selection." msgstr "" +"Si vous n’avez pas le contrôle de votre routeur, choisissez de ne pas le " +"configurer. Pour voir les options permettant de surmonter cette limitation, " +"choisissez l’option « pas d’adresses publique » dans la sélection du type de " +"connexion à Internet." #: plinth/modules/networks/templates/router_configuration_content.html:39 msgid "Choose How You Wish to Configure Your Router" -msgstr "" +msgstr "Choisissez comment vous souhaitez configurer votre routeur" #: plinth/modules/networks/templates/router_configuration_content.html:42 msgid "" @@ -6686,10 +6706,8 @@ msgid "" msgstr "" #: plinth/modules/wireguard/forms.py:82 -#, fuzzy -#| msgid "A list of IP addresses, separated by space" msgid "Client IP address provided by server" -msgstr "Une liste d'adresses IP séparées par des espaces" +msgstr "Adresse IP client fournie par le serveur" #: plinth/modules/wireguard/forms.py:83 msgid "" @@ -6720,6 +6738,9 @@ msgid "" "layer of security. Fill in only if provided. Example: " "MConEJFIg6+DFHg2J1nn9SNLOSE9KR0ysdPgmPjibEs=." msgstr "" +"Optionnel. Une clé secrète partagée fournie par le serveur pour ajouter un " +"niveau supplémentaire de sécurité. Ne remplir que si une clé est fournie. " +"Exemple : MConEJFIg6+DFHg2J1nn9SNLOSE9KR0ysdPgmPjibEs=." #: plinth/modules/wireguard/forms.py:105 msgid "Use this connection to send all outgoing traffic" @@ -6730,25 +6751,21 @@ msgid "Typically checked for a VPN service though which all traffic is sent." msgstr "" #: plinth/modules/wireguard/templates/wireguard.html:10 -#, fuzzy -#| msgid "Chat Server" msgid "As a Server" -msgstr "Serveur de discussion" +msgstr "En tant que serveur" #: plinth/modules/wireguard/templates/wireguard.html:12 msgid "Peers allowed to connect to this server:" -msgstr "" +msgstr "Pairs autorisés à se connecter à ce serveur :" #: plinth/modules/wireguard/templates/wireguard.html:18 msgid "Allowed IPs" -msgstr "" +msgstr "IP autorisées" #: plinth/modules/wireguard/templates/wireguard.html:19 #: plinth/modules/wireguard/templates/wireguard.html:75 -#, fuzzy -#| msgid "Create Connection" msgid "Last Connected Time" -msgstr "Créer Connexion" +msgstr "Date de dernière connexion" #: plinth/modules/wireguard/templates/wireguard.html:38 #, python-format @@ -6758,89 +6775,67 @@ msgstr "" #: plinth/modules/wireguard/templates/wireguard.html:47 #, python-format msgid "Public key for this %(box_name)s:" -msgstr "" +msgstr "Clé publique pour ce %(box_name)s :" #: plinth/modules/wireguard/templates/wireguard.html:53 -#, fuzzy -#| msgid "No shares currently configured." msgid "Not configured yet." -msgstr "Aucun partage actuellement configuré." +msgstr "Pas encore configuré." #: plinth/modules/wireguard/templates/wireguard.html:57 -#, fuzzy -#| msgid "Add new introducer" msgid "Add a new peer" -msgstr "Ajouter un nouvel introducteur" +msgstr "Ajouter un nouveau pair" #: plinth/modules/wireguard/templates/wireguard.html:61 #: plinth/modules/wireguard/views.py:51 msgid "Add Allowed Client" -msgstr "" +msgstr "Ajouter un client autorisé" #: plinth/modules/wireguard/templates/wireguard.html:64 -#, fuzzy -#| msgid "Chat Client" msgid "As a Client" -msgstr "Client de discussion" +msgstr "En tant que client" #: plinth/modules/wireguard/templates/wireguard.html:66 #, python-format msgid "Servers that %(box_name)s will connect to:" -msgstr "" +msgstr "Serveurs auxquels %(box_name)s va se connecter :" #: plinth/modules/wireguard/templates/wireguard.html:73 #: plinth/modules/wireguard/templates/wireguard_delete_server.html:19 msgid "Endpoint" -msgstr "" +msgstr "Endpoint" #: plinth/modules/wireguard/templates/wireguard.html:96 -#, fuzzy -#| msgid "Authentication to remote server failed." msgid "No connections to remote servers are configured yet." -msgstr "Échec de l'authentification sur le serveur distant." +msgstr "Aucune connexion vers le serveur distant n’est encore configurée." #: plinth/modules/wireguard/templates/wireguard.html:104 -#, fuzzy -#| msgid "Add new introducer" msgid "Add a new server" -msgstr "Ajouter un nouvel introducteur" +msgstr "Ajouter un nouveau serveur" #: plinth/modules/wireguard/templates/wireguard.html:108 #: plinth/modules/wireguard/views.py:160 -#, fuzzy -#| msgid "Add Connection" msgid "Add Connection to Server" -msgstr "Ajouter connexion" +msgstr "Ajouter connexion au serveur" #: plinth/modules/wireguard/templates/wireguard_add_client.html:19 -#, fuzzy -#| msgid "IRC Client" msgid "Add Client" -msgstr "Client IRC" +msgstr "Ajouter un client" #: plinth/modules/wireguard/templates/wireguard_delete_client.html:14 -#, fuzzy -#| msgid "Are you sure that you want to remove this repository?" msgid "Are you sure that you want to delete this client?" -msgstr "Êtes-vous sûr de vouloir supprimer ce dépôt ?" +msgstr "Voulez-vous vraiment supprimer ce client ?" #: plinth/modules/wireguard/templates/wireguard_delete_server.html:14 -#, fuzzy -#| msgid "Are you sure that you want to remove this repository?" msgid "Are you sure that you want to delete this server?" -msgstr "Êtes-vous sûr de vouloir supprimer ce dépôt ?" +msgstr "Voulez-vous vraiment supprimer ce serveur ?" #: plinth/modules/wireguard/templates/wireguard_edit_client.html:19 -#, fuzzy -#| msgid "Chat Client" msgid "Update Client" -msgstr "Client de discussion" +msgstr "Mettre à jour le client" #: plinth/modules/wireguard/templates/wireguard_edit_server.html:19 -#, fuzzy -#| msgid "Create Connection" msgid "Update Connection" -msgstr "Créer Connexion" +msgstr "Mettre à jour la connexion" #: plinth/modules/wireguard/templates/wireguard_show_client.html:12 #, python-format @@ -6863,10 +6858,8 @@ msgid "Pre-shared key:" msgstr "" #: plinth/modules/wireguard/templates/wireguard_show_client.html:32 -#, fuzzy -#| msgid "Server domain" msgid "Server endpoints:" -msgstr "Domaine du serveur" +msgstr "Endpoints du serveur :" #: plinth/modules/wireguard/templates/wireguard_show_client.html:40 #: plinth/modules/wireguard/templates/wireguard_show_server.html:27 From e7afa69155d8ac6fd11349e6348f06f83fab8873 Mon Sep 17 00:00:00 2001 From: Veiko Aasa Date: Tue, 25 Feb 2020 15:29:32 +0200 Subject: [PATCH 05/41] storage: Directory selection form improvements - Action script: - must not be root when validating directory - return only first validation error - Directory selection form, transmission, deluge: show the download path as it is in the configuration, the path is resolved only on form submit. - Tests: add relative path checks, refactor parametrize code Signed-off-by: Veiko Aasa Reviewed-by: James Valleroy --- actions/storage | 8 +++- plinth/modules/deluge/forms.py | 2 +- plinth/modules/deluge/views.py | 4 +- plinth/modules/storage/forms.py | 2 +- plinth/modules/storage/tests/test_storage.py | 50 ++++++-------------- plinth/modules/transmission/forms.py | 2 +- plinth/modules/transmission/views.py | 4 +- 7 files changed, 26 insertions(+), 46 deletions(-) diff --git a/actions/storage b/actions/storage index a3a11ef1e..508dc6d11 100755 --- a/actions/storage +++ b/actions/storage @@ -333,6 +333,9 @@ def subcommand_usage_info(_): def subcommand_validate_directory(arguments): """Validate a directory""" + if os.geteuid() == 0: + raise RuntimeError('You must not be root to run this command') + directory = arguments.path def part_exists(path): @@ -349,14 +352,15 @@ def subcommand_validate_directory(arguments): if not os.path.exists(directory): # doesn't exist print('ValidationError: 1') + return if not os.path.isdir(directory): # is not a directory print('ValidationError: 2') - if not os.access(directory, os.R_OK): + elif not os.access(directory, os.R_OK): # is not readable print('ValidationError: 3') - if arguments.check_writable or arguments.check_creatable: + elif arguments.check_writable or arguments.check_creatable: if not os.access(directory, os.W_OK): # is not writable print('ValidationError: 4') diff --git a/plinth/modules/deluge/forms.py b/plinth/modules/deluge/forms.py index e85dc8792..a969cb301 100644 --- a/plinth/modules/deluge/forms.py +++ b/plinth/modules/deluge/forms.py @@ -18,5 +18,5 @@ class DelugeForm(DirectorySelectForm): check_creatable=True) super(DelugeForm, self).__init__( title=_('Download directory'), - default='/var/lib/deluged/Downloads/', validator=validator, *args, + default='/var/lib/deluged/Downloads', validator=validator, *args, **kw) diff --git a/plinth/modules/deluge/views.py b/plinth/modules/deluge/views.py index 78576fbae..4547d6ab7 100644 --- a/plinth/modules/deluge/views.py +++ b/plinth/modules/deluge/views.py @@ -4,7 +4,6 @@ Django views for Deluge. """ import json -import os from django.contrib import messages from django.utils.translation import ugettext as _ @@ -25,8 +24,7 @@ class DelugeAppView(views.AppView): status = super().get_initial() configuration = json.loads( actions.superuser_run('deluge', ['get-configuration'])) - status['storage_path'] = os.path.normpath( - configuration['download_location']) + status['storage_path'] = configuration['download_location'] return status def form_valid(self, form): diff --git a/plinth/modules/storage/forms.py b/plinth/modules/storage/forms.py index 89501529f..d871dd3b5 100644 --- a/plinth/modules/storage/forms.py +++ b/plinth/modules/storage/forms.py @@ -103,7 +103,7 @@ class DirectorySelectForm(AppForm): if title: self.fields['storage_dir'].label = title self.validator = validator - self.default = os.path.normpath(default) + self.default = default self.set_form_data() def clean(self): diff --git a/plinth/modules/storage/tests/test_storage.py b/plinth/modules/storage/tests/test_storage.py index 60c01192f..c277ef762 100644 --- a/plinth/modules/storage/tests/test_storage.py +++ b/plinth/modules/storage/tests/test_storage.py @@ -250,45 +250,25 @@ class TestActions: assert output == error @pytest.mark.usefixtures('needs_not_root') - @pytest.mark.parametrize('directory', [{ - 'path': '/missing', - 'error': '1' - }, { - 'path': '/etc/os-release', - 'error': '2' - }, { - 'path': '/root', - 'error': '3' - }, { - 'path': '/', - 'error': '' - }]) - def test_validate_directory(self, directory): + @pytest.mark.parametrize('path,error', [('/missing', '1'), + ('/etc/os-release', '2'), + ('/root', '3'), ('/', ''), + ('/etc/..', '')]) + def test_validate_directory(self, path, error): """Test that directory validation returns expected output.""" - self.assert_validate_directory(directory['path'], directory['error']) + self.assert_validate_directory(path, error) @pytest.mark.usefixtures('needs_not_root') - @pytest.mark.parametrize('directory', [{ - 'path': '/', - 'error': '4' - }, { - 'path': '/tmp', - 'error': '' - }]) - def test_validate_directory_writable(self, directory): + @pytest.mark.parametrize('path,error', [('/', '4'), ('/tmp', '')]) + def test_validate_directory_writable(self, path, error): """Test that directory writable validation returns expected output.""" - self.assert_validate_directory(directory['path'], directory['error'], - check_writable=True) + self.assert_validate_directory(path, error, check_writable=True) @pytest.mark.usefixtures('needs_not_root') - @pytest.mark.parametrize('directory', [{ - 'path': '/var/lib/plinth_storage_test_not_exists', - 'error': '4' - }, { - 'path': '/tmp/plint_storage_test_not_exists', - 'error': '' - }]) - def test_validate_directory_creatable(self, directory): + @pytest.mark.parametrize( + 'path,error', [('/var/lib/plinth_storage_test_not_exists', '4'), + ('/tmp/plint_storage_test_not_exists', ''), + ('/var/../tmp/plint_storage_test_not_exists', '')]) + def test_validate_directory_creatable(self, path, error): """Test that directory creatable validation returns expected output.""" - self.assert_validate_directory(directory['path'], directory['error'], - check_creatable=True) + self.assert_validate_directory(path, error, check_creatable=True) diff --git a/plinth/modules/transmission/forms.py b/plinth/modules/transmission/forms.py index 9eb059eeb..95f251a62 100644 --- a/plinth/modules/transmission/forms.py +++ b/plinth/modules/transmission/forms.py @@ -18,5 +18,5 @@ class TransmissionForm(DirectorySelectForm): username=reserved_usernames[0], check_writable=True) super(TransmissionForm, self).__init__( title=_('Download directory'), - default='/var/lib/transmission-daemon/downloads/', + default='/var/lib/transmission-daemon/downloads', validator=validator, *args, **kw) diff --git a/plinth/modules/transmission/views.py b/plinth/modules/transmission/views.py index b0a0bde59..84319ecfb 100644 --- a/plinth/modules/transmission/views.py +++ b/plinth/modules/transmission/views.py @@ -5,7 +5,6 @@ FreedomBox app for configuring Transmission Server. import json import logging -import os import socket from django.contrib import messages @@ -29,8 +28,7 @@ class TransmissionAppView(views.AppView): configuration = actions.superuser_run('transmission', ['get-configuration']) configuration = json.loads(configuration) - status['storage_path'] = os.path.normpath( - configuration['download-dir']) + status['storage_path'] = configuration['download-dir'] status['hostname'] = socket.gethostname() return status From 141ef33f7e73dc6bcb4432d4d3fb1f8fe56a5d5e Mon Sep 17 00:00:00 2001 From: Veiko Aasa Date: Tue, 25 Feb 2020 15:32:42 +0200 Subject: [PATCH 06/41] transmission: Allow to submit download directory if it is creatable transmission-deamon creates the directory if it doesn't exist. Signed-off-by: Veiko Aasa Reviewed-by: James Valleroy --- plinth/modules/transmission/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plinth/modules/transmission/forms.py b/plinth/modules/transmission/forms.py index 95f251a62..30a081cee 100644 --- a/plinth/modules/transmission/forms.py +++ b/plinth/modules/transmission/forms.py @@ -15,7 +15,7 @@ class TransmissionForm(DirectorySelectForm): def __init__(self, *args, **kw): validator = DirectoryValidator( - username=reserved_usernames[0], check_writable=True) + username=reserved_usernames[0], check_creatable=True) super(TransmissionForm, self).__init__( title=_('Download directory'), default='/var/lib/transmission-daemon/downloads', From ef4bd69c2a7ba910d95833f81de6ee04a3094b66 Mon Sep 17 00:00:00 2001 From: "Luis A. Arizmendi" Date: Tue, 3 Mar 2020 21:23:39 +0000 Subject: [PATCH 07/41] Translated using Weblate (Spanish) Currently translated at 100.0% (1265 of 1265 strings) --- plinth/locale/es/LC_MESSAGES/django.po | 151 ++++++++++--------------- 1 file changed, 60 insertions(+), 91 deletions(-) diff --git a/plinth/locale/es/LC_MESSAGES/django.po b/plinth/locale/es/LC_MESSAGES/django.po index eff146421..322fdc938 100644 --- a/plinth/locale/es/LC_MESSAGES/django.po +++ b/plinth/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-02-24 19:12-0500\n" -"PO-Revision-Date: 2020-02-24 21:32+0000\n" +"PO-Revision-Date: 2020-03-04 22:32+0000\n" "Last-Translator: Luis A. Arizmendi \n" "Language-Team: Spanish \n" @@ -649,10 +649,8 @@ msgid "Enable Domain Name System Security Extensions" msgstr "Activar Extensiones de Seguridad del Sistema de Nombre de Dominios" #: plinth/modules/bind/templates/bind.html:11 -#, fuzzy -#| msgid "Server domain" msgid "Serving Domains" -msgstr "Dominio del servidor" +msgstr "Dominios en servicio" #: plinth/modules/bind/templates/bind.html:16 #: plinth/modules/ikiwiki/forms.py:12 @@ -662,27 +660,21 @@ msgid "Type" msgstr "Tipo" #: plinth/modules/bind/templates/bind.html:17 -#, fuzzy -#| msgid "Domain Name" msgid "Domain Names" -msgstr "Nombre de dominio" +msgstr "Nombres de dominio" #: plinth/modules/bind/templates/bind.html:18 -#, fuzzy -#| msgid "Service" msgid "Serving" -msgstr "Servicio" +msgstr "En servicio" #: plinth/modules/bind/templates/bind.html:19 -#, fuzzy -#| msgid "IP address" msgid "IP addresses" -msgstr "Dirección IP" +msgstr "Direcciones IP" #: plinth/modules/bind/templates/bind.html:35 #: plinth/modules/bind/templates/bind.html:37 msgid "Refresh IP address and domains" -msgstr "" +msgstr "Actualizar direcciones IP y dominios" #: plinth/modules/bind/views.py:73 plinth/modules/deluge/views.py:46 #: plinth/modules/dynamicdns/views.py:150 plinth/modules/openvpn/views.py:134 @@ -3534,7 +3526,7 @@ msgstr "Abierto" #: plinth/modules/networks/forms.py:297 msgid "Choose your internet connection type" -msgstr "" +msgstr "Elija su tipo de conexión a Internet" #: plinth/modules/networks/forms.py:301 msgid "" @@ -3546,6 +3538,14 @@ msgid "" "connectivity. If you have a public IP address but are unsure if it changes " "over time or not, it is safer to choose this option.

" msgstr "" +"Tengo una dirección IP pública que cambia cada cierto tiempo

Implica que otros dispositivos en Internet pueden acceder a su " +"equipo cuando está conectado a Internet. Cada vez que se conecta a través de " +"su proveedor de servicio Internet (ISP) puede que obtenga una dirección IP " +"diferente, sobre todo si ha estado un tiempo desconectado. Muchos " +"proveedores ofrecen este tipo de conexión. Si tienen una dirección IP " +"pública pero no sabe si cambia cada cierto tiempo, elegir esta opción es lo " +"más seguro.

" #: plinth/modules/networks/forms.py:313 #, python-brace-format @@ -3558,6 +3558,13 @@ msgid "" "but very few ISPs offer this. You may be able to get this service from your " "ISP by making an additional payment.

" msgstr "" +"Tengo una dirección IP pública que no cambia (recomendada)

Implica que otros dispositivos pueden acceder a su equipo cuando " +"éste está conectado a Internet. Cada vez que se conecta a Internet a través " +"de su proveedor de servicios (ISP) obtiene la misma dirección IP. Es la " +"configuración más estable para muchos servicios de {box_name} pero muy pocos " +"ISP la ofrecen. Puede que su proveedor ofrezca esta posibilidad con un pago " +"adicional.

" #: plinth/modules/networks/forms.py:326 #, python-brace-format @@ -3570,20 +3577,21 @@ msgid "" "troublesome situation for hosting services at home. {box_name} provides many " "workaround solutions but each solution has some limitations.

" msgstr "" +"No tengo una dirección IP pública

Implica que otros " +"dispositivos en Internet no pueden acceder a su equipo aunque éste " +"esté conectado a Internet. Cada vez que se conecta con su proveedor de " +"servicios de Internet (ISP) obtiene una dirección IP válida solo para " +"entornos de red local. Muchos ISP ofrecen este tipo de conexión. Es la más " +"proclive a problemas para los servicios de auto-hospedaje doméstico. " +"{box_name} proporciona algunas soluciones pero todas presentan algunas " +"limitaciones.

" #: plinth/modules/networks/forms.py:351 msgid "Preferred router configuration" msgstr "Configuración del router preferida" #: plinth/modules/networks/forms.py:356 -#, fuzzy, python-brace-format -#| msgid "" -#| "Use DMZ feature to forward all traffic

Most " -#| "routers provide a configuration setting called DMZ. This will allow the " -#| "router to forward all incoming traffic from the internet to a single IP " -#| "address such as the {box_name}'s address. First remember to configure a " -#| "static local IP address for your {box_name} in your router's " -#| "configuration.

" +#, python-brace-format msgid "" "Use DMZ feature to forward all traffic (recommended)

Most routers provide a configuration setting called DMZ. This will allow " @@ -3592,23 +3600,14 @@ msgid "" "static local IP address for your {box_name} in your router's configuration." msgstr "" -"Emplee DMZ para dirigir el tráfico de la red

. La " -"mayoría de los routers proporcionan una función DMZ que permite dirigir el " -"tráfico entrante de Internet a una única dirección IP como puede ser la de " -"{box_name}. Recuerde configurar su {box_name} con una IP estática en su " -"router.

" +"Emplee DMZ para dirigir el tráfico de la red (recomendada)

. La mayoría de los routers proporcionan una función DMZ que permite " +"dirigir el tráfico entrante de Internet a una única dirección IP como puede " +"ser la de su {box_name}. Recuerde configurar su {box_name} con una IP " +"estática en su router.

" #: plinth/modules/networks/forms.py:368 -#, fuzzy, python-brace-format -#| msgid "" -#| "Forward Specific Traffic as needed by each application

You may alternatively choose to forward only specific traffic to " -#| "your {box_name}. This is ideal if you have other servers like {box_name} " -#| "in your network or if your router does not support DMZ feature. All " -#| "applications that provide a web interface need you to forward traffic " -#| "from ports 80 and 443 to work. Each of the other applications will " -#| "suggest which port(s) need to be forwarded for that application to work." +#, python-brace-format msgid "" "Forward specific traffic as needed by each application

You may alternatively choose to forward only specific traffic to your " @@ -3618,21 +3617,15 @@ msgid "" "443 to work. Each of the other applications will suggest which port(s) need " "to be forwarded for that application to work.

" msgstr "" -"Redirigir el tráfico de aplicaciones específicas

. " -"Puede redirigir solo el tráfico de determinadas aplicaciones a su " -"{box_name}. Es la opción recomendad si tiene otros servidores como " -"{box_name} en su red o si su router no soporta la función DMZ. Todas las " -"aplicaciones con interfaz web necesitarán redirigir el tráfico de los " -"puertos 80 y 443 para funcionar. Otras aplicaciones sugerirán qué puertos es " -"necesario redirigir para su funcionamiento.

" +"Redirigir el tráfico de aplicaciones específicas

" +"Puede redirigir solo el tráfico de determinadas aplicaciones a su {box_name}" +". Es la opción recomendada si tiene otros servidores como {box_name} en su " +"red o si su router no soporta la función DMZ. Todas las aplicaciones con " +"interfaz web necesitarán redirigir el tráfico de los puertos 80 y 443 para " +"funcionar. Otras aplicaciones sugerirán qué puertos es necesario redirigir " +"para su funcionamiento.

" #: plinth/modules/networks/forms.py:382 -#, fuzzy -#| msgid "" -#| "Router is currently unconfigured

Choose this if " -#| "you have not configured or are unable to configure the router currently " -#| "and wish to be reminded later. Some of the other configuration steps may " -#| "fail.

" msgid "" "Router is currently unconfigured

Choose this if you " "have not configured or are unable to configure the router currently and wish " @@ -3640,8 +3633,8 @@ msgid "" msgstr "" "El router no está configurado

Elija esta opción si " "no ha configurado o no puede configurar el router en este momento y desea " -"que se le recuerde más tarde. Puede que alguno de los siguientes pasos de la " -"configuración falle.

" +"que se le recuerde más tarde. Puede que falle alguno de los siguientes pasos " +"de la configuración.

" #: plinth/modules/networks/networks.py:32 msgid "Network Connections" @@ -3743,10 +3736,8 @@ msgid "Router configuration type saved." msgstr "Se ha guardado la configuración del router." #: plinth/modules/networks/networks.py:474 -#, fuzzy -#| msgid "Router configuration type saved." msgid "Internet connection type saved." -msgstr "Se ha guardado la configuración del router." +msgstr "Se ha guardado el tipo de conexión a Internet." #: plinth/modules/networks/templates/connection_show.html:28 msgid "Edit connection" @@ -3999,25 +3990,18 @@ msgstr "Crear…" #: plinth/modules/networks/templates/internet_connectivity_content.html:10 msgid "What Type Of Internet Connection Do You Have?" -msgstr "" +msgstr "¿Qué tipo de conexión a Internet tiene?" #: plinth/modules/networks/templates/internet_connectivity_content.html:16 -#, fuzzy -#| msgid "" -#| "The following best describes how your %(box_name)s is connected in your " -#| "network. This information is used only to suggest necessary configuration " -#| "actions." msgid "" "Select an option that best describes the type of Internet connection. This " "information is used only to guide you with further setup." msgstr "" -"Lo siguiente describe cómo se conecta su %(box_name)s a su red. Esta " +"Elija la opción que mejor describa el tipo de conexión a Internet. Esta " "información se emplea solo para sugerir otras configuraciones necesarias." #: plinth/modules/networks/templates/internet_connectivity_firstboot.html:18 #: plinth/modules/networks/templates/router_configuration_firstboot.html:18 -#, fuzzy -#| msgid "skip this step" msgid "Skip this step" msgstr "Saltar este paso" @@ -4027,36 +4011,31 @@ msgid "Next" msgstr "Siguiente" #: plinth/modules/networks/templates/internet_connectivity_main.html:9 -#, fuzzy -#| msgid "Connection Type" msgid "Your Internet Connection Type" -msgstr "Tipo de conexión" +msgstr "Tipo de su conexión a Internet" #: plinth/modules/networks/templates/internet_connectivity_main.html:14 -#, fuzzy -#| msgid "" -#| "The following best describes how your %(box_name)s is connected in your " -#| "network. This information is used only to suggest necessary configuration " -#| "actions." msgid "" "The following best describes the type of Internet connection provided by " "your ISP. This information is only used to suggest you necessary " "configuration actions." msgstr "" -"Lo siguiente describe cómo se conecta su %(box_name)s a su red. Esta " -"información se emplea solo para sugerir otras configuraciones necesarias." +"Lo siguiente describe el tipo de conexión a Internet ofrecida por su ISP. " +"Esta información se emplea solo para sugerir otras configuraciones " +"necesarias." #: plinth/modules/networks/templates/internet_connectivity_main.html:23 msgid "My ISP provides a public IP address that does not change over time." -msgstr "" +msgstr "Mi ISP proporciona una dirección IP pública permanente." #: plinth/modules/networks/templates/internet_connectivity_main.html:27 msgid "My ISP provides a public IP address that may change over time." msgstr "" +"Mi ISP proporciona una dirección IP pública que cambia cada cierto tiempo." #: plinth/modules/networks/templates/internet_connectivity_main.html:31 msgid "My ISP does not provide a public IP address." -msgstr "" +msgstr "Mi ISP no proporciona una dirección IP pública." #: plinth/modules/networks/templates/internet_connectivity_main.html:37 #: plinth/modules/networks/templates/router_configuration_main.html:29 @@ -4091,18 +4070,13 @@ msgstr "" "provee los servicios." #: plinth/modules/networks/templates/router_configuration_content.html:32 -#, fuzzy -#| msgid "" -#| "If you don't have control over your router, choose not to configure it. " -#| "To see options, to overcome this limitation, choose 'no public address' " -#| "option in Internet connection type selection." msgid "" "If you don't have control over your router, choose not to configure it. To " "see options to overcome this limitation, choose 'no public address' option " "in Internet connection type selection." msgstr "" "Si no tiene acceso a su router, elija la opción de no configurarlo. Para ver " -"opciones para superar esta limitación, elija la opción \"sin dirección " +"opciones para solucionar esta limitación, elija la opción \"sin dirección " "pública\" en los tipos de conexión a Internet." #: plinth/modules/networks/templates/router_configuration_content.html:39 @@ -4149,16 +4123,13 @@ msgstr "" "información se emplea solo para sugerir otras configuraciones necesarias." #: plinth/modules/networks/templates/router_configuration_main.html:23 -#, fuzzy, python-format -#| msgid "" -#| "Your %(box_name)s gets its internet from your Router via WiFi or Ethernet " -#| "cable. This is a typical home setup." +#, python-format msgid "" "Your %(box_name)s gets its Internet from your Router via Wi-Fi or Ethernet " "cable. This is a typical home setup." msgstr "" "Su %(box_name)s accede a Internet a través de su router vía Wi-Fi o cable " -"Ethernet. Es la configuración doméstica habitual." +"Ethernet. Ésta es la configuración doméstica habitual." #: plinth/modules/openvpn/__init__.py:26 #, python-brace-format @@ -4198,10 +4169,8 @@ msgid "Enable OpenVPN server" msgstr "Activar servidor OpenVPN" #: plinth/modules/openvpn/manifest.py:48 -#, fuzzy -#| msgid "TunnelBlick" msgid "Tunnelblick" -msgstr "TunnelBlick" +msgstr "Tunnelblick" #: plinth/modules/openvpn/templates/openvpn.html:27 #, python-format From 04b9538debdad07cb9351fda3d0ca1e9be6f4dbe Mon Sep 17 00:00:00 2001 From: Veiko Aasa Date: Tue, 3 Mar 2020 10:02:59 +0200 Subject: [PATCH 08/41] plinth: Increase sqlite busy timeout from default 5s to 30s Reduces the probability that plinth gives an error 500 because the database is locked. Test performed: 1) Lock the database: > sqlite3 data/var/lib/plinth/plinth.sqlite3 sqlite> PRAGMA locking_mode = EXCLUSIVE; sqlite> BEGIN EXCLUSIVE; 2) Visit plinth/apps/ 3) Only after 30s plinth logs an exception: django.db.utils.OperationalError: database is locked Closes #1786 Related to #1443 Signed-off-by: Veiko Aasa [sunil: Move the timeout value to settings module as it is static] Signed-off-by: Sunil Mohan Adapa Reviewed-by: Sunil Mohan Adapa --- plinth/settings.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plinth/settings.py b/plinth/settings.py index effb75744..dbdd97f35 100644 --- a/plinth/settings.py +++ b/plinth/settings.py @@ -67,6 +67,9 @@ CAPTCHA_FLITE_PATH = '/usr/bin/flite' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', + 'OPTIONS': { + 'timeout': 30 + }, # Overridden based on the configuration key store_file 'NAME': '/var/lib/plinth/plinth.sqlite3' } From b668e62f6fc94eaec465be512ec1bf27b4117475 Mon Sep 17 00:00:00 2001 From: Veiko Aasa Date: Sun, 1 Mar 2020 11:20:23 +0200 Subject: [PATCH 09/41] upgrades: Clean apt cache every week Closes #973 Signed-off-by: Veiko Aasa Reviewed-by: Sunil Mohan Adapa --- plinth/modules/upgrades/data/etc/apt/apt.conf.d/20freedombox | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plinth/modules/upgrades/data/etc/apt/apt.conf.d/20freedombox b/plinth/modules/upgrades/data/etc/apt/apt.conf.d/20freedombox index 7f5c6dce2..574055587 100644 --- a/plinth/modules/upgrades/data/etc/apt/apt.conf.d/20freedombox +++ b/plinth/modules/upgrades/data/etc/apt/apt.conf.d/20freedombox @@ -6,3 +6,6 @@ APT::Update::Post-Invoke-Success { "/usr/bin/test -S /var/run/dbus/system_bus_socket && /usr/bin/gdbus call --system --dest org.freedombox.Service --object-path /org/freedombox/Service/PackageHandler --timeout 10 --method org.freedombox.Service.PackageHandler.CacheUpdated 2> /dev/null > /dev/null; /bin/echo > /dev/null"; }; + +// Clean apt cache every 7 days +APT::Periodic::CleanInterval "7"; From 995af05866bb163e2791b9478e3fa25d1961c811 Mon Sep 17 00:00:00 2001 From: Veiko Aasa Date: Sat, 29 Feb 2020 14:18:59 +0200 Subject: [PATCH 10/41] apps: Do not show status block if service is running If at least one related service/daemon is not running, show the alert if app is enabled, otherwise set alert as hidden (for functional tests). Closes #1752 Signed-off-by: Veiko Aasa [sunil: Minor code simplification in app template, status section] Signed-off-by: Sunil Mohan Adapa Reviewed-by: Sunil Mohan Adapa --- functional_tests/support/service.py | 4 ++-- plinth/modules/bind/views.py | 1 - plinth/modules/cockpit/views.py | 1 - plinth/modules/config/views.py | 1 - plinth/modules/coquelicot/views.py | 1 - plinth/modules/gitweb/views.py | 1 - plinth/modules/i2p/views.py | 1 - plinth/modules/ikiwiki/views.py | 1 - plinth/modules/jsxc/views.py | 1 - plinth/modules/mediawiki/views.py | 1 - plinth/modules/minetest/views.py | 1 - plinth/modules/mldonkey/urls.py | 6 +----- plinth/modules/openvpn/views.py | 1 - plinth/modules/roundcube/urls.py | 5 ++--- plinth/modules/searx/views.py | 1 - plinth/modules/shaarli/urls.py | 4 +--- plinth/modules/storage/views.py | 1 - plinth/modules/syncthing/urls.py | 5 ++--- plinth/modules/tor/views.py | 1 - plinth/modules/ttrss/urls.py | 3 +-- plinth/modules/upgrades/views.py | 1 - plinth/modules/users/views.py | 1 - plinth/modules/wireguard/views.py | 1 - plinth/templates/app.html | 24 +++++++----------------- plinth/views.py | 8 -------- 25 files changed, 16 insertions(+), 60 deletions(-) diff --git a/functional_tests/support/service.py b/functional_tests/support/service.py index 1ef4470a8..2ddbe5ef9 100644 --- a/functional_tests/support/service.py +++ b/functional_tests/support/service.py @@ -23,12 +23,12 @@ def get_service_module(service_name): def is_running(browser, service_name): interface.nav_to_module(browser, get_service_module(service_name)) - return len(browser.find_by_css('.running-status.active')) != 0 + return len(browser.find_by_id('service-not-running')) == 0 def is_not_running(browser, service_name): interface.nav_to_module(browser, get_service_module(service_name)) - return len(browser.find_by_css('.running-status.inactive')) != 0 + return len(browser.find_by_id('service-not-running')) != 0 def eventually(function, args=[], timeout=30): diff --git a/plinth/modules/bind/views.py b/plinth/modules/bind/views.py index 165667743..ab0cf9a55 100644 --- a/plinth/modules/bind/views.py +++ b/plinth/modules/bind/views.py @@ -17,7 +17,6 @@ from .forms import BindForm class BindAppView(AppView): # pylint: disable=too-many-ancestors """A specialized view for configuring Bind.""" app_id = 'bind' - show_status_block = True form_class = BindForm template_name = 'bind.html' port_forwarding_info = port_forwarding_info diff --git a/plinth/modules/cockpit/views.py b/plinth/modules/cockpit/views.py index 3be255cfe..231e6c67d 100644 --- a/plinth/modules/cockpit/views.py +++ b/plinth/modules/cockpit/views.py @@ -8,7 +8,6 @@ from plinth.views import AppView class CockpitAppView(AppView): app_id = 'cockpit' - show_status_block = True template_name = 'cockpit.html' def get_context_data(self, *args, **kwargs): diff --git a/plinth/modules/config/views.py b/plinth/modules/config/views.py index 96511beb8..abc89095b 100644 --- a/plinth/modules/config/views.py +++ b/plinth/modules/config/views.py @@ -22,7 +22,6 @@ class ConfigAppView(views.AppView): """Serve configuration page.""" form_class = ConfigurationForm app_id = 'config' - show_status_block = False def get_initial(self): """Return the current status""" diff --git a/plinth/modules/coquelicot/views.py b/plinth/modules/coquelicot/views.py index 7c62467f1..46d9aed0e 100644 --- a/plinth/modules/coquelicot/views.py +++ b/plinth/modules/coquelicot/views.py @@ -17,7 +17,6 @@ class CoquelicotAppView(views.AppView): """Serve configuration page.""" app_id = 'coquelicot' form_class = CoquelicotForm - show_status_block = True def get_initial(self): """Return the status of the service to fill in the form.""" diff --git a/plinth/modules/gitweb/views.py b/plinth/modules/gitweb/views.py index 0b549fcf0..3c9c6d9f3 100644 --- a/plinth/modules/gitweb/views.py +++ b/plinth/modules/gitweb/views.py @@ -23,7 +23,6 @@ class GitwebAppView(views.AppView): """Serve configuration page.""" app_id = 'gitweb' - show_status_block = False template_name = 'gitweb_configure.html' def get_context_data(self, *args, **kwargs): diff --git a/plinth/modules/i2p/views.py b/plinth/modules/i2p/views.py index 3672be0d2..a809f113d 100644 --- a/plinth/modules/i2p/views.py +++ b/plinth/modules/i2p/views.py @@ -26,7 +26,6 @@ subsubmenu = [{ class I2PAppView(AppView): """Serve configuration page.""" app_id = 'i2p' - show_status_block = True template_name = 'i2p.html' def get_context_data(self, **kwargs): diff --git a/plinth/modules/ikiwiki/views.py b/plinth/modules/ikiwiki/views.py index c4e83b322..82b02747e 100644 --- a/plinth/modules/ikiwiki/views.py +++ b/plinth/modules/ikiwiki/views.py @@ -18,7 +18,6 @@ from .forms import IkiwikiCreateForm class IkiwikiAppView(views.AppView): """Serve configuration page.""" app_id = 'ikiwiki' - show_status_block = False template_name = 'ikiwiki_configure.html' def get_context_data(self, **kwargs): diff --git a/plinth/modules/jsxc/views.py b/plinth/modules/jsxc/views.py index 53cab4382..b025b9263 100644 --- a/plinth/modules/jsxc/views.py +++ b/plinth/modules/jsxc/views.py @@ -13,7 +13,6 @@ class JSXCAppView(AppView): """Show ejabberd as an app.""" app_id = 'jsxc' template_name = 'jsxc.html' - show_status_block = False class JsxcView(TemplateView): diff --git a/plinth/modules/mediawiki/views.py b/plinth/modules/mediawiki/views.py index f45e7b6c8..689824944 100644 --- a/plinth/modules/mediawiki/views.py +++ b/plinth/modules/mediawiki/views.py @@ -22,7 +22,6 @@ class MediaWikiAppView(views.AppView): """App configuration page.""" app_id = 'mediawiki' form_class = MediaWikiForm - show_status_block = False template_name = 'mediawiki.html' def get_initial(self): diff --git a/plinth/modules/minetest/views.py b/plinth/modules/minetest/views.py index 81fb616e7..4e4f6da63 100644 --- a/plinth/modules/minetest/views.py +++ b/plinth/modules/minetest/views.py @@ -17,7 +17,6 @@ from .forms import MinetestForm class MinetestAppView(AppView): # pylint: disable=too-many-ancestors """A specialized view for configuring minetest.""" app_id = 'minetest' - show_status_block = True template_name = 'minetest.html' form_class = MinetestForm port_forwarding_info = minetest.port_forwarding_info diff --git a/plinth/modules/mldonkey/urls.py b/plinth/modules/mldonkey/urls.py index 444827632..edb5ec743 100644 --- a/plinth/modules/mldonkey/urls.py +++ b/plinth/modules/mldonkey/urls.py @@ -8,9 +8,5 @@ from django.conf.urls import url from plinth.views import AppView urlpatterns = [ - url(r'^apps/mldonkey/$', - AppView.as_view( - app_id='mldonkey', - show_status_block=True, - ), name='index'), + url(r'^apps/mldonkey/$', AppView.as_view(app_id='mldonkey'), name='index') ] diff --git a/plinth/modules/openvpn/views.py b/plinth/modules/openvpn/views.py index 66283e9b0..064678089 100644 --- a/plinth/modules/openvpn/views.py +++ b/plinth/modules/openvpn/views.py @@ -48,7 +48,6 @@ def index(request): 'port_forwarding_info': openvpn.port_forwarding_info, 'status': status, 'form': form, - 'show_status_block': True, 'is_running': status['is_running'], 'has_diagnostics': True, 'is_enabled': status['enabled'], diff --git a/plinth/modules/roundcube/urls.py b/plinth/modules/roundcube/urls.py index 87593c338..5c7a79c76 100644 --- a/plinth/modules/roundcube/urls.py +++ b/plinth/modules/roundcube/urls.py @@ -8,7 +8,6 @@ from django.conf.urls import url from plinth.views import AppView urlpatterns = [ - url(r'^apps/roundcube/$', - AppView.as_view(app_id='roundcube', show_status_block=False), - name='index'), + url(r'^apps/roundcube/$', AppView.as_view(app_id='roundcube'), + name='index') ] diff --git a/plinth/modules/searx/views.py b/plinth/modules/searx/views.py index 193a83750..2aa212e0f 100644 --- a/plinth/modules/searx/views.py +++ b/plinth/modules/searx/views.py @@ -17,7 +17,6 @@ class SearxAppView(views.AppView): """Serve configuration page.""" app_id = 'searx' form_class = SearxForm - show_status_block = False def get_initial(self): """Return the status of the service to fill in the form.""" diff --git a/plinth/modules/shaarli/urls.py b/plinth/modules/shaarli/urls.py index 9322231f3..0800f18cb 100644 --- a/plinth/modules/shaarli/urls.py +++ b/plinth/modules/shaarli/urls.py @@ -8,7 +8,5 @@ from django.conf.urls import url from plinth.views import AppView urlpatterns = [ - url(r'^apps/shaarli/$', - AppView.as_view(app_id='shaarli', show_status_block=False), - name='index'), + url(r'^apps/shaarli/$', AppView.as_view(app_id='shaarli'), name='index') ] diff --git a/plinth/modules/storage/views.py b/plinth/modules/storage/views.py index 0296a37a2..7a239372f 100644 --- a/plinth/modules/storage/views.py +++ b/plinth/modules/storage/views.py @@ -26,7 +26,6 @@ class StorageAppView(views.AppView): """Show storage information.""" app_id = 'storage' template_name = 'storage.html' - show_status_block = False def get_context_data(self, *args, **kwargs): """Return template context data.""" diff --git a/plinth/modules/syncthing/urls.py b/plinth/modules/syncthing/urls.py index bf4d738bf..1f1a9f05b 100644 --- a/plinth/modules/syncthing/urls.py +++ b/plinth/modules/syncthing/urls.py @@ -8,7 +8,6 @@ from django.conf.urls import url from plinth.views import AppView urlpatterns = [ - url(r'^apps/syncthing/$', - AppView.as_view(app_id='syncthing', show_status_block=True), - name='index'), + url(r'^apps/syncthing/$', AppView.as_view(app_id='syncthing'), + name='index') ] diff --git a/plinth/modules/tor/views.py b/plinth/modules/tor/views.py index daa885280..14b74b0b8 100644 --- a/plinth/modules/tor/views.py +++ b/plinth/modules/tor/views.py @@ -45,7 +45,6 @@ def index(request): 'firewall': tor.app.get_components_of_type(Firewall), 'has_diagnostics': True, 'is_enabled': status['enabled'], - 'show_status_block': True, 'is_running': status['is_running'], }) diff --git a/plinth/modules/ttrss/urls.py b/plinth/modules/ttrss/urls.py index 00336ffc6..19bee29ff 100644 --- a/plinth/modules/ttrss/urls.py +++ b/plinth/modules/ttrss/urls.py @@ -8,6 +8,5 @@ from django.conf.urls import url from plinth.views import AppView urlpatterns = [ - url(r'^apps/ttrss/$', - AppView.as_view(app_id='ttrss', show_status_block=True), name='index'), + url(r'^apps/ttrss/$', AppView.as_view(app_id='ttrss'), name='index') ] diff --git a/plinth/modules/upgrades/views.py b/plinth/modules/upgrades/views.py index c269cdc9c..08d9786c8 100644 --- a/plinth/modules/upgrades/views.py +++ b/plinth/modules/upgrades/views.py @@ -23,7 +23,6 @@ class UpgradesConfigurationView(AppView): success_url = reverse_lazy('upgrades:index') template_name = "upgrades_configure.html" app_id = 'upgrades' - show_status_block = False def get_initial(self): return {'auto_upgrades_enabled': upgrades.is_enabled()} diff --git a/plinth/modules/users/views.py b/plinth/modules/users/views.py index 9f07acdd8..d51014a1c 100644 --- a/plinth/modules/users/views.py +++ b/plinth/modules/users/views.py @@ -58,7 +58,6 @@ class UserList(AppView, ContextMixin, django.views.generic.ListView): template_name = 'users_list.html' title = ugettext_lazy('Users') app_id = 'users' - show_status_block = False def get_context_data(self, *args, **kwargs): context = super(UserList, self).get_context_data(*args, **kwargs) diff --git a/plinth/modules/wireguard/views.py b/plinth/modules/wireguard/views.py index 0c9d0c261..43dbf3f75 100644 --- a/plinth/modules/wireguard/views.py +++ b/plinth/modules/wireguard/views.py @@ -25,7 +25,6 @@ class WireguardView(AppView): """Serve configuration page.""" app_id = 'wireguard' diagnostics_module_name = 'wireguard' - show_status_block = False template_name = 'wireguard.html' port_forwarding_info = wireguard.port_forwarding_info diff --git a/plinth/templates/app.html b/plinth/templates/app.html index 10f64dddf..30e2b6855 100644 --- a/plinth/templates/app.html +++ b/plinth/templates/app.html @@ -23,23 +23,13 @@ {% endblock %} {% block status %} - {% if show_status_block %} -

{% trans "Status" %}

-

- {% with service_name=app_info.name %} - {% if is_running %} - - {% blocktrans trimmed %} - Service {{ service_name }} is running. - {% endblocktrans %} - {% else %} - - {% blocktrans trimmed %} - Service {{ service_name }} is not running. - {% endblocktrans %} - {% endif %} - {% endwith %} -

+ {% if is_running is not None and not is_running %} + {% endif %} {% endblock %} diff --git a/plinth/views.py b/plinth/views.py index eb288422d..f98144a90 100644 --- a/plinth/views.py +++ b/plinth/views.py @@ -117,9 +117,6 @@ class AppView(FormView): 'form_class' is the Django form class that is used by this view. By default the AppForm class is used. - 'show_status_block' is a boolean to determine if the status section must be - shown in this app's page. - 'template_name' is the template used to render this view. By default it is app.html. It may be overridden with a template that derives from app.html to customize the appearance of the app to achieve more complex presentation @@ -131,10 +128,6 @@ class AppView(FormView): """ form_class = forms.AppForm - # Display the 'status' block of the app.html template - # This block uses information from service.is_running. This method is - # optional, so allow not showing this block here. - show_status_block = True app_id = None template_name = 'app.html' port_forwarding_info = None @@ -202,7 +195,6 @@ class AppView(FormView): context['is_running'] = app_is_running(self.app) context['app_info'] = self.app.info context['has_diagnostics'] = self.app.has_diagnostics() - context['show_status_block'] = self.show_status_block context['port_forwarding_info'] = self.port_forwarding_info from plinth.modules.firewall.components import Firewall From 1dd75990b1216c685700dcf6ca7038825e69be50 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 29 Feb 2020 19:50:34 -0500 Subject: [PATCH 11/41] avahi: Use generic app view Tests performed: - Visit avahi app view. - Enable/disable avahi. Signed-off-by: Sunil Mohan Adapa Reviewed-by: Veiko Aasa --- plinth/modules/avahi/__init__.py | 5 ----- plinth/modules/avahi/urls.py | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/plinth/modules/avahi/__init__.py b/plinth/modules/avahi/__init__.py index 8f9fee070..75eb28745 100644 --- a/plinth/modules/avahi/__init__.py +++ b/plinth/modules/avahi/__init__.py @@ -14,7 +14,6 @@ from plinth.modules.firewall.components import Firewall from plinth.modules.names.components import DomainType from plinth.signals import domain_added, domain_removed, post_hostname_change from plinth.utils import format_lazy -from plinth.views import AppView from .manifest import backup # noqa, pylint: disable=unused-import @@ -109,7 +108,3 @@ def on_post_hostname_change(sender, old_hostname, new_hostname, **kwargs): name=old_hostname + '.local') domain_added.send_robust(sender='avahi', domain_type='domain-type-local', name=new_hostname + '.local', services='__all__') - - -class AvahiAppView(AppView): - app_id = 'avahi' diff --git a/plinth/modules/avahi/urls.py b/plinth/modules/avahi/urls.py index d8b9c8630..698c721de 100644 --- a/plinth/modules/avahi/urls.py +++ b/plinth/modules/avahi/urls.py @@ -5,8 +5,8 @@ URLs for the service discovery module. from django.conf.urls import url -from plinth.modules.avahi import AvahiAppView +from plinth.views import AppView urlpatterns = [ - url(r'^sys/avahi/$', AvahiAppView.as_view(), name='index'), + url(r'^sys/avahi/$', AppView.as_view(app_id='avahi'), name='index'), ] From fe5bdf290b5e4cd6431e7f6202d54235971dc6bf Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 29 Feb 2020 19:51:18 -0500 Subject: [PATCH 12/41] privoxy: Use generic app view Tests performed: - Visit privoxy app view. - Enable/disable privoxy app. Signed-off-by: Sunil Mohan Adapa Reviewed-by: Veiko Aasa --- plinth/modules/privoxy/__init__.py | 5 ----- plinth/modules/privoxy/urls.py | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/plinth/modules/privoxy/__init__.py b/plinth/modules/privoxy/__init__.py index 7033f7dc9..40ee6c082 100644 --- a/plinth/modules/privoxy/__init__.py +++ b/plinth/modules/privoxy/__init__.py @@ -13,7 +13,6 @@ from plinth.daemon import Daemon from plinth.modules.apache.components import diagnose_url from plinth.modules.firewall.components import Firewall from plinth.utils import format_lazy -from plinth.views import AppView from .manifest import backup # noqa, pylint: disable=unused-import @@ -104,10 +103,6 @@ def setup(helper, old_version=None): helper.call('post', app.enable) -class PrivoxyAppView(AppView): - app_id = 'privoxy' - - def diagnose_url_with_proxy(): """Run a diagnostic on a URL with a proxy.""" url = 'https://debian.org/' # Gives a simple redirect to www. diff --git a/plinth/modules/privoxy/urls.py b/plinth/modules/privoxy/urls.py index f540f20b0..eb908a8c4 100644 --- a/plinth/modules/privoxy/urls.py +++ b/plinth/modules/privoxy/urls.py @@ -5,8 +5,8 @@ URLs for the Privoxy module. from django.conf.urls import url -from plinth.modules.privoxy import PrivoxyAppView +from plinth.views import AppView urlpatterns = [ - url(r'^apps/privoxy/$', PrivoxyAppView.as_view(), name='index'), + url(r'^apps/privoxy/$', AppView.as_view(app_id='privoxy'), name='index'), ] From ea1e7e953f9cbd9e1fc7c8a66c093aae35b2c12e Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 29 Feb 2020 19:52:30 -0500 Subject: [PATCH 13/41] infinoted: Move views to a separate views module Tests performed: - Visit infinoted app view. - Enable/disable infinoted. Signed-off-by: Sunil Mohan Adapa Reviewed-by: Veiko Aasa --- plinth/modules/infinoted/__init__.py | 6 ------ plinth/modules/infinoted/urls.py | 2 +- plinth/modules/infinoted/views.py | 12 ++++++++++++ 3 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 plinth/modules/infinoted/views.py diff --git a/plinth/modules/infinoted/__init__.py b/plinth/modules/infinoted/__init__.py index 65f6a5d61..f65d0f8a3 100644 --- a/plinth/modules/infinoted/__init__.py +++ b/plinth/modules/infinoted/__init__.py @@ -12,7 +12,6 @@ from plinth import cfg, frontpage, menu from plinth.daemon import Daemon from plinth.modules.firewall.components import Firewall from plinth.utils import format_lazy -from plinth.views import AppView from .manifest import backup, clients # noqa, pylint: disable=unused-import @@ -83,11 +82,6 @@ def init(): app.set_enabled(True) -class InfinotedAppView(AppView): - app_id = 'infinoted' - port_forwarding_info = port_forwarding_info - - def setup(helper, old_version=None): """Install and configure the module.""" helper.install(managed_packages) diff --git a/plinth/modules/infinoted/urls.py b/plinth/modules/infinoted/urls.py index 600387ddf..eb1352b9c 100644 --- a/plinth/modules/infinoted/urls.py +++ b/plinth/modules/infinoted/urls.py @@ -5,7 +5,7 @@ URLs for the infinoted module. from django.conf.urls import url -from plinth.modules.infinoted import InfinotedAppView +from .views import InfinotedAppView urlpatterns = [ url(r'^apps/infinoted/$', InfinotedAppView.as_view(), name='index'), diff --git a/plinth/modules/infinoted/views.py b/plinth/modules/infinoted/views.py new file mode 100644 index 000000000..089354e4d --- /dev/null +++ b/plinth/modules/infinoted/views.py @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: AGPL-3.0-or-later +""" +Views for the infinoted app. +""" +from plinth.modules import infinoted +from plinth.views import AppView + + +class InfinotedAppView(AppView): + """Main app view for Infinoted.""" + app_id = 'infinoted' + port_forwarding_info = infinoted.port_forwarding_info From 95d0923788096447e21f1a5b551b52b390be839e Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 29 Feb 2020 19:53:25 -0500 Subject: [PATCH 14/41] help: Rename views modules as 'views' Tests performed: - Visit help main view by visiting URL /plinth/help/. - Visit pages: about, manual, get support, submit feedback, contribute. - Download manual. - Raise an exception in a view, visit the view in non-develop mode, see the status log. Signed-off-by: Sunil Mohan Adapa Reviewed-by: Veiko Aasa --- plinth/modules/help/urls.py | 2 +- plinth/modules/help/{help.py => views.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename plinth/modules/help/{help.py => views.py} (100%) diff --git a/plinth/modules/help/urls.py b/plinth/modules/help/urls.py index 57d3febcd..1a7d41a17 100644 --- a/plinth/modules/help/urls.py +++ b/plinth/modules/help/urls.py @@ -7,7 +7,7 @@ from django.conf.urls import url from plinth.utils import non_admin_view -from . import help as views +from . import views urlpatterns = [ url(r'^help/$', non_admin_view(views.index), name='index'), diff --git a/plinth/modules/help/help.py b/plinth/modules/help/views.py similarity index 100% rename from plinth/modules/help/help.py rename to plinth/modules/help/views.py From cfc3b1924fb67b866cf5f0033859683c2b8e95a7 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 29 Feb 2020 19:54:40 -0500 Subject: [PATCH 15/41] networks: Rename views modules as 'views' Tests performed: - Visit networks main view to list network connections. - Add an Ethernet connection, view it and delete it. Signed-off-by: Sunil Mohan Adapa Reviewed-by: Veiko Aasa --- plinth/modules/networks/urls.py | 2 +- plinth/modules/networks/{networks.py => views.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename plinth/modules/networks/{networks.py => views.py} (100%) diff --git a/plinth/modules/networks/urls.py b/plinth/modules/networks/urls.py index 637ca3f7f..861b481e7 100644 --- a/plinth/modules/networks/urls.py +++ b/plinth/modules/networks/urls.py @@ -5,7 +5,7 @@ URLs for the Network module from django.conf.urls import url -from . import networks as views +from . import views urlpatterns = [ url(r'^sys/networks/$', views.index, name='index'), diff --git a/plinth/modules/networks/networks.py b/plinth/modules/networks/views.py similarity index 100% rename from plinth/modules/networks/networks.py rename to plinth/modules/networks/views.py From d8e5d63616a7cac111d44a90a70e9b3b96eb8010 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 29 Feb 2020 19:55:03 -0500 Subject: [PATCH 16/41] diagnostics: Rename views modules, move utilities to main module Tests performed: - Visit diagnostics app. - Run diagnostics for all apps. - Go to privoxy app and run diagnostics. Signed-off-by: Sunil Mohan Adapa Reviewed-by: Veiko Aasa --- plinth/modules/diagnostics/__init__.py | 67 ++++++++++++++ plinth/modules/diagnostics/diagnostics.py | 108 ---------------------- plinth/modules/diagnostics/urls.py | 2 +- plinth/modules/diagnostics/views.py | 40 ++++++++ 4 files changed, 108 insertions(+), 109 deletions(-) delete mode 100644 plinth/modules/diagnostics/diagnostics.py create mode 100644 plinth/modules/diagnostics/views.py diff --git a/plinth/modules/diagnostics/__init__.py b/plinth/modules/diagnostics/__init__.py index d79896c83..3afb3303b 100644 --- a/plinth/modules/diagnostics/__init__.py +++ b/plinth/modules/diagnostics/__init__.py @@ -3,6 +3,11 @@ FreedomBox app for system diagnostics. """ +import collections +import importlib +import logging +import threading + from django.utils.translation import ugettext_lazy as _ from plinth import app as app_module @@ -23,6 +28,12 @@ _description = [ app = None +logger = logging.Logger(__name__) + +running_task = None + +current_results = {} + class DiagnosticsApp(app_module.App): """FreedomBox app for diagnostics.""" @@ -59,3 +70,59 @@ def init(): global app app = DiagnosticsApp() app.set_enabled(True) + + +def start_task(): + """Start the run task in a separate thread.""" + global running_task + if running_task: + raise Exception('Task already running') + + running_task = threading.Thread(target=_run_on_all_enabled_modules_wrapper) + running_task.start() + + +def _run_on_all_enabled_modules_wrapper(): + """Wrapper over actual task to catch exceptions.""" + try: + run_on_all_enabled_modules() + except Exception as exception: + logger.exception('Error running diagnostics - %s', exception) + current_results['error'] = str(exception) + + global running_task + running_task = None + + +def run_on_all_enabled_modules(): + """Run diagnostics on all the enabled modules and store the result.""" + global current_results + current_results = { + 'apps': [], + 'results': collections.OrderedDict(), + 'progress_percentage': 0 + } + + apps = [] + for app in app_module.App.list(): + # XXX: Implement more cleanly. + # Don't run diagnostics on apps have not been setup yet. + # However, run on apps that need an upgrade. + module = importlib.import_module(app.__class__.__module__) + if module.setup_helper.get_state() == 'needs-setup': + continue + + if not app.is_enabled(): + continue + + if not app.has_diagnostics(): + continue + + apps.append((app.app_id, app)) + current_results['results'][app.app_id] = None + + current_results['apps'] = apps + for current_index, (app_id, app) in enumerate(apps): + current_results['results'][app_id] = app.diagnose() + current_results['progress_percentage'] = \ + int((current_index + 1) * 100 / len(apps)) diff --git a/plinth/modules/diagnostics/diagnostics.py b/plinth/modules/diagnostics/diagnostics.py deleted file mode 100644 index 81f854319..000000000 --- a/plinth/modules/diagnostics/diagnostics.py +++ /dev/null @@ -1,108 +0,0 @@ -# SPDX-License-Identifier: AGPL-3.0-or-later -""" -FreedomBox app for running diagnostics. -""" - -import collections -import importlib -import logging -import threading - -from django.http import Http404 -from django.template.response import TemplateResponse -from django.utils.translation import ugettext_lazy as _ -from django.views.decorators.http import require_POST - -from plinth.app import App -from plinth.modules import diagnostics - -logger = logging.Logger(__name__) - -current_results = {} - -_running_task = None - - -def index(request): - """Serve the index page""" - if request.method == 'POST' and not _running_task: - _start_task() - - return TemplateResponse( - request, 'diagnostics.html', { - 'app_info': diagnostics.app.info, - 'is_running': _running_task is not None, - 'results': current_results - }) - - -@require_POST -def diagnose_app(request, app_id): - """Return diagnostics for a particular app.""" - try: - app = App.get(app_id) - except KeyError: - raise Http404('App does not exist') - - return TemplateResponse(request, 'diagnostics_app.html', { - 'title': _('Diagnostic Test'), - 'app_id': app_id, - 'results': app.diagnose() - }) - - -def _start_task(): - """Start the run task in a separate thread.""" - global _running_task - if _running_task: - raise Exception('Task already running') - - _running_task = threading.Thread( - target=_run_on_all_enabled_modules_wrapper) - _running_task.start() - - -def _run_on_all_enabled_modules_wrapper(): - """Wrapper over actual task to catch exceptions.""" - try: - run_on_all_enabled_modules() - except Exception as exception: - logger.exception('Error running diagnostics - %s', exception) - current_results['error'] = str(exception) - - global _running_task - _running_task = None - - -def run_on_all_enabled_modules(): - """Run diagnostics on all the enabled modules and store the result.""" - global current_results - current_results = { - 'apps': [], - 'results': collections.OrderedDict(), - 'progress_percentage': 0 - } - - apps = [] - for app in App.list(): - # XXX: Implement more cleanly. - # Don't run diagnostics on apps have not been setup yet. - # However, run on apps that need an upgrade. - module = importlib.import_module(app.__class__.__module__) - if module.setup_helper.get_state() == 'needs-setup': - continue - - if not app.is_enabled(): - continue - - if not app.has_diagnostics(): - continue - - apps.append((app.app_id, app)) - current_results['results'][app.app_id] = None - - current_results['apps'] = apps - for current_index, (app_id, app) in enumerate(apps): - current_results['results'][app_id] = app.diagnose() - current_results['progress_percentage'] = \ - int((current_index + 1) * 100 / len(apps)) diff --git a/plinth/modules/diagnostics/urls.py b/plinth/modules/diagnostics/urls.py index e4c34e463..2c6c692ba 100644 --- a/plinth/modules/diagnostics/urls.py +++ b/plinth/modules/diagnostics/urls.py @@ -5,7 +5,7 @@ URLs for the Diagnostics module from django.conf.urls import url -from . import diagnostics as views +from . import views urlpatterns = [ url(r'^sys/diagnostics/$', views.index, name='index'), diff --git a/plinth/modules/diagnostics/views.py b/plinth/modules/diagnostics/views.py new file mode 100644 index 000000000..9b441032e --- /dev/null +++ b/plinth/modules/diagnostics/views.py @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: AGPL-3.0-or-later +""" +FreedomBox app for running diagnostics. +""" + +from django.http import Http404 +from django.template.response import TemplateResponse +from django.utils.translation import ugettext_lazy as _ +from django.views.decorators.http import require_POST + +from plinth.app import App +from plinth.modules import diagnostics + + +def index(request): + """Serve the index page""" + if request.method == 'POST' and not diagnostics.running_task: + diagnostics.start_task() + + return TemplateResponse( + request, 'diagnostics.html', { + 'app_info': diagnostics.app.info, + 'is_running': diagnostics.running_task is not None, + 'results': diagnostics.current_results + }) + + +@require_POST +def diagnose_app(request, app_id): + """Return diagnostics for a particular app.""" + try: + app = App.get(app_id) + except KeyError: + raise Http404('App does not exist') + + return TemplateResponse(request, 'diagnostics_app.html', { + 'title': _('Diagnostic Test'), + 'app_id': app_id, + 'results': app.diagnose() + }) From 4e24eca25d4dacb00934dd1eae85912925ae6eee Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 29 Feb 2020 20:30:45 -0500 Subject: [PATCH 17/41] backups: cosmetic: Rename .inc file to .html Tests performed: - Go to backups page. - Take a backup and see it listed in list of repositories. Signed-off-by: Sunil Mohan Adapa Reviewed-by: Veiko Aasa --- plinth/modules/backups/templates/backups.html | 2 +- .../{backups_repository.inc => backups_repository.html} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename plinth/modules/backups/templates/{backups_repository.inc => backups_repository.html} (100%) diff --git a/plinth/modules/backups/templates/backups.html b/plinth/modules/backups/templates/backups.html index bce7f56c1..b519e79b6 100644 --- a/plinth/modules/backups/templates/backups.html +++ b/plinth/modules/backups/templates/backups.html @@ -58,7 +58,7 @@

{% trans 'Existing Backups' %}

{% for repository in repositories %} - {% include "backups_repository.inc" with uuid=repository.uuid %} + {% include "backups_repository.html" with uuid=repository.uuid %} {% endfor %} {% endblock %} diff --git a/plinth/modules/backups/templates/backups_repository.inc b/plinth/modules/backups/templates/backups_repository.html similarity index 100% rename from plinth/modules/backups/templates/backups_repository.inc rename to plinth/modules/backups/templates/backups_repository.html From b51ccff7431d7dca34fc685f3159fc92b804becb Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 29 Feb 2020 21:09:01 -0500 Subject: [PATCH 18/41] css: Merge responsive.css into main style file - Eliminate issue with collapsed navbar's drop-down menu text color when the width is exactly 768px or less than 320px. - Remove redundant footer's position: relative rule. Tests performed: - Change the browser width to 768px, the navbar is not collapsed and drop down menu text color is black on white background. - Change the browser width to 767px, the navbar is collapsed and drop down menu text color is white on blue background. - Change the browser width to less than 320px, the navbar is collapsed and drop down menu text color is white on blue background. - Footer on the main page and remaining pages is unchanged at <320px, =767px and >= 768px. Signed-off-by: Sunil Mohan Adapa Reviewed-by: Veiko Aasa --- plinth/templates/base.html | 1 - static/themes/default/css/plinth.css | 7 +++++++ static/themes/default/css/responsive.css | 17 ----------------- 3 files changed, 7 insertions(+), 18 deletions(-) delete mode 100644 static/themes/default/css/responsive.css diff --git a/plinth/templates/base.html b/plinth/templates/base.html index 7c6a146a5..0a47e762e 100644 --- a/plinth/templates/base.html +++ b/plinth/templates/base.html @@ -56,7 +56,6 @@ - diff --git a/static/themes/default/css/plinth.css b/static/themes/default/css/plinth.css index 857364a21..f3da16ee2 100644 --- a/static/themes/default/css/plinth.css +++ b/static/themes/default/css/plinth.css @@ -293,6 +293,13 @@ footer { background: transparent; } +@media screen and (max-width: 767px) { + .main-header.navbar-default .navbar-nav>.open .dropdown-menu > li > a, + .main-header.navbar-default .navbar-nav>.open .dropdown-menu > li > a:hover { + color: #FFF; + } +} + .navbar-default .navbar-toggle .icon-bar { background-color: #FFF; } diff --git a/static/themes/default/css/responsive.css b/static/themes/default/css/responsive.css deleted file mode 100644 index 7c772c62b..000000000 --- a/static/themes/default/css/responsive.css +++ /dev/null @@ -1,17 +0,0 @@ -/* -# SPDX-License-Identifier: AGPL-3.0-or-later -*/ -/* Responsive queries */ -/* Smartphone */ - -@media only screen and (min-width: 320px) and (max-width: 768px) { - footer{ - position: relative; - } - - .navbar-default .navbar-nav .open .dropdown-menu > li > a, - .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover { - color: #FFF; - } - -} From 673bd367b07b768b9e41209dc23e1748d619d2b8 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 29 Feb 2020 21:35:31 -0500 Subject: [PATCH 19/41] css: cosmetic: Rename plinth.css to main.css Tests performed: - Visit an app page, install page and home page. Signed-off-by: Sunil Mohan Adapa Reviewed-by: Veiko Aasa --- plinth/templates/base.html | 2 +- static/themes/default/css/{plinth.css => main.css} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename static/themes/default/css/{plinth.css => main.css} (100%) diff --git a/plinth/templates/base.html b/plinth/templates/base.html index 0a47e762e..3b9308a80 100644 --- a/plinth/templates/base.html +++ b/plinth/templates/base.html @@ -55,7 +55,7 @@ - + diff --git a/static/themes/default/css/plinth.css b/static/themes/default/css/main.css similarity index 100% rename from static/themes/default/css/plinth.css rename to static/themes/default/css/main.css From 9a9c99da8139df3074f8a4f1ddc79b18c072de14 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 29 Feb 2020 22:03:11 -0500 Subject: [PATCH 20/41] views: Don't send app to template context - Improves template security as methods of the app object can't be called from within templates. Tests performed: - Visit a few app pages. - For each of the following template files, ensure that 'app' variable is not used: - app.html - All templates that extend app.html - Templates included from the above templates. Signed-off-by: Sunil Mohan Adapa Reviewed-by: Veiko Aasa --- plinth/views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plinth/views.py b/plinth/views.py index f98144a90..d13b97b70 100644 --- a/plinth/views.py +++ b/plinth/views.py @@ -190,7 +190,6 @@ class AppView(FormView): """Add service to the context data.""" context = super().get_context_data(*args, **kwargs) context.update(self._get_common_status()) - context['app'] = self.app # XXX: Remove this for template security context['app_id'] = self.app.app_id context['is_running'] = app_is_running(self.app) context['app_info'] = self.app.info From b3ccb75d2df387038376e4927272d8f2f99bd143 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Wed, 4 Mar 2020 14:17:57 -0800 Subject: [PATCH 21/41] app: Fix showing app name in port forwarding information Fixes: #1784. Signed-off-by: Sunil Mohan Adapa Reviewed-by: Veiko Aasa --- plinth/templates/app.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plinth/templates/app.html b/plinth/templates/app.html index 30e2b6855..4eac53460 100644 --- a/plinth/templates/app.html +++ b/plinth/templates/app.html @@ -38,7 +38,7 @@ {% endblock %} {% block port_forwarding_info %} - {% include "port-forwarding-info.html" with service_name=name %} + {% include "port-forwarding-info.html" with service_name=app_info.name %} {% endblock %} {% block configuration %} From a2710f1edea4183064177224fa4104f0d38b17be Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Wed, 4 Mar 2020 10:21:54 -0800 Subject: [PATCH 22/41] networks: Rename polkit JS authority rules file Add a comment explaining when .pkla file is used and when the .rules file is used. Tests performed: - Install policykit-1 version 0.105. Something like apt install policykit-1=0.105-26 libpolkit-agent-1-0=0.105-26 libpolkit-gobject-1-0=0.105-26 - View list of network connections. - Add a network connection. - View a network connection's details page. - Delete a network connection. - Add Debian experimental to /etc/apt/sources.list. apt update. Then install policykit-1 version 0.116. apt install -t experimental policykit-1. - Repeat all above tests. Signed-off-by: Sunil Mohan Adapa Reviewed-by: Veiko Aasa --- .../{50-plinth.rules => 50-freedombox-network-manager.rules} | 5 +++++ 1 file changed, 5 insertions(+) rename plinth/modules/networks/data/usr/share/polkit-1/rules.d/{50-plinth.rules => 50-freedombox-network-manager.rules} (55%) diff --git a/plinth/modules/networks/data/usr/share/polkit-1/rules.d/50-plinth.rules b/plinth/modules/networks/data/usr/share/polkit-1/rules.d/50-freedombox-network-manager.rules similarity index 55% rename from plinth/modules/networks/data/usr/share/polkit-1/rules.d/50-plinth.rules rename to plinth/modules/networks/data/usr/share/polkit-1/rules.d/50-freedombox-network-manager.rules index b5c3b8867..795cdf81b 100644 --- a/plinth/modules/networks/data/usr/share/polkit-1/rules.d/50-plinth.rules +++ b/plinth/modules/networks/data/usr/share/polkit-1/rules.d/50-freedombox-network-manager.rules @@ -1,5 +1,10 @@ /* # SPDX-License-Identifier: AGPL-3.0-or-later + +This file is used only by policykit-1 version > 0.105. A corresponding .pkla +file is used by policykit-1 <= 0.105. See: +https://davidz25.blogspot.com/2012/06/authorization-rules-in-polkit.html + */ polkit.addRule(function(action, subject) { From 2361c9e0b6b3792ca82a2ffdda670dbc59e8fa8e Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Wed, 4 Mar 2020 10:26:33 -0800 Subject: [PATCH 23/41] firewalld: Add polkit JS authority rules files This should help with FreedomBox getting authorizations to access firewalld D-Bus API for polkit versions > 0.105 where polkit local authority is not available. Helps #1728. Tests performed: - Install policykit-1 version 0.105. Something like apt install policykit-1=0.105-26 libpolkit-agent-1-0=0.105-26 libpolkit-gobject-1-0=0.105-26 - Visit privoxy page. See internal networks warning with all the interfaces listed properly. - Visit firewalld page, view list of apps and services properly. - Enable privoxy, see the port opened in firewalld page. - Disable privoxy, see the port closed in firewalld page. - Run diagnostics for privoxy see that ports' diagnostics results pass. - Add Debian experimental to /etc/apt/sources.list. apt update. Then install policykit-1 version 0.116. apt install -t experimental policykit-1. - Repeat all above tests. Signed-off-by: Sunil Mohan Adapa Reviewed-by: Veiko Aasa --- .../rules.d/50-freedombox-firewalld.rules | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 plinth/modules/firewall/data/usr/share/polkit-1/rules.d/50-freedombox-firewalld.rules diff --git a/plinth/modules/firewall/data/usr/share/polkit-1/rules.d/50-freedombox-firewalld.rules b/plinth/modules/firewall/data/usr/share/polkit-1/rules.d/50-freedombox-firewalld.rules new file mode 100644 index 000000000..ff9edc2dd --- /dev/null +++ b/plinth/modules/firewall/data/usr/share/polkit-1/rules.d/50-freedombox-firewalld.rules @@ -0,0 +1,16 @@ +/* +# SPDX-License-Identifier: AGPL-3.0-or-later + +This file is used only by policykit-1 version > 0.105. A corresponding .pkla +file is used by policykit-1 <= 0.105. See: +https://davidz25.blogspot.com/2012/06/authorization-rules-in-polkit.html + +*/ + +polkit.addRule(function(action, subject) { + if ((action.id == "org.fedoraproject.FirewallD1.config.info" || + action.id == "org.fedoraproject.FirewallD1.config") && + subject.user == "plinth") { + return polkit.Result.YES; + } +}); From 3b8308b0cf787bab3e7662be187c6b0dc3f36d26 Mon Sep 17 00:00:00 2001 From: Nektarios Katakis Date: Fri, 28 Feb 2020 14:24:33 +0000 Subject: [PATCH 24/41] networks: Add form for network topology Signed-off-by: Nektarios Katakis [sunil: Use the term 'network topology' consistently] [sunil: Minor grammer fix, and spacing for i18n] Signed-off-by: Sunil Mohan Adapa Reviewed-by: Sunil Mohan Adapa --- plinth/modules/networks/forms.py | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/plinth/modules/networks/forms.py b/plinth/modules/networks/forms.py index 2443d7c73..5467509ce 100644 --- a/plinth/modules/networks/forms.py +++ b/plinth/modules/networks/forms.py @@ -285,6 +285,48 @@ requires clients to have the password to connect.'), return settings +class NetworkTopologyForm(forms.Form): + """Form to ask the user for network topology. + + That is how the FreedomBox is connected to the internal network topology. + Store this information for future suggestions when setting up services. + + """ + network_topology = forms.ChoiceField( + label=format_lazy( + _('Choose how your {box_name} is connected to your network'), + box_name=cfg.box_name), + required=True, + widget=forms.RadioSelect, + choices=[ + ('to_router', + format_lazy( + _('Connected to a router ' + '

Your {box_name} gets its Internet ' + 'connection from your router via Wi-Fi or Ethernet cable. ' + 'This is a typical home setup.

'), box_name=cfg.box_name, + allow_markup=True)), + ('as_router', + format_lazy( + _('{box_name} is your router ' + '

Your {box_name} has multiple ' + 'network interfaces such as multiple Ethernet ports or ' + 'a Wi-Fi adapter. {box_name} is directly connected to the ' + 'Internet and all your devices connect to {box_name} ' + 'for their Internet connectivity.

'), + box_name=cfg.box_name, allow_markup=True)), + ('direct', + format_lazy( + _('Directly connected to the Internet ' + '

Your Internet connection is ' + 'directly attached to your {box_name} and there are no ' + 'other devices on the network. This can happen on ' + 'community or cloud setups.

'), box_name=cfg.box_name, + allow_markup=True)), + ], + ) + + class InternetConnectionTypeForm(forms.Form): """Form for type of public/private IP address ISP provides. From e0e0a5dd60873f2060a3a10c07dbd770b0f18da2 Mon Sep 17 00:00:00 2001 From: Nektarios Katakis Date: Fri, 28 Feb 2020 15:39:50 +0000 Subject: [PATCH 25/41] networks: Add page for network topology form Signed-off-by: Nektarios Katakis [sunil: Use the term 'network topology' consistently] [sunil: Properly title case the

title] Signed-off-by: Sunil Mohan Adapa Reviewed-by: Sunil Mohan Adapa --- .../templates/network_topology_content.html | 21 +++++++++++++++++++ .../templates/network_topology_update.html | 21 +++++++++++++++++++ plinth/modules/networks/urls.py | 2 ++ plinth/modules/networks/views.py | 17 ++++++++++++++- 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 plinth/modules/networks/templates/network_topology_content.html create mode 100644 plinth/modules/networks/templates/network_topology_update.html diff --git a/plinth/modules/networks/templates/network_topology_content.html b/plinth/modules/networks/templates/network_topology_content.html new file mode 100644 index 000000000..5cd08dfc2 --- /dev/null +++ b/plinth/modules/networks/templates/network_topology_content.html @@ -0,0 +1,21 @@ +{% comment %} +# SPDX-License-Identifier: AGPL-3.0-or-later +{% endcomment %} + +{% load bootstrap %} +{% load i18n %} +{% load static %} + +

+ {% blocktrans trimmed %} + How is Your {{ box_name }} Connected to the Internet? + {% endblocktrans %} +

+ +

+ {% blocktrans trimmed %} + Select an option that best describes how your {{ box_name }} is connected in + your network. This information is used to guide you with further setup. It can + be changed later. + {% endblocktrans %} +

diff --git a/plinth/modules/networks/templates/network_topology_update.html b/plinth/modules/networks/templates/network_topology_update.html new file mode 100644 index 000000000..507614722 --- /dev/null +++ b/plinth/modules/networks/templates/network_topology_update.html @@ -0,0 +1,21 @@ +{% extends "base.html" %} +{% comment %} +# SPDX-License-Identifier: AGPL-3.0-or-later +{% endcomment %} + +{% load bootstrap %} +{% load i18n %} +{% load static %} + +{% block content %} + {% include "network_topology_content.html" %} + +
+ {% csrf_token %} + + {{ form|bootstrap }} + + +
+ +{% endblock %} diff --git a/plinth/modules/networks/urls.py b/plinth/modules/networks/urls.py index 861b481e7..873a5e51e 100644 --- a/plinth/modules/networks/urls.py +++ b/plinth/modules/networks/urls.py @@ -37,4 +37,6 @@ urlpatterns = [ url(r'^sys/networks/firstboot/internet-connection-type/$', views.InternetConnectionTypeFirstBootView.as_view(), name='internet-connection-type-first-boot'), + url(r'^sys/networks/network-topology/$', + views.NetworkTopologyView.as_view(), name='network-topology'), ] diff --git a/plinth/modules/networks/views.py b/plinth/modules/networks/views.py index 0616fddd7..0b7ca5fd5 100644 --- a/plinth/modules/networks/views.py +++ b/plinth/modules/networks/views.py @@ -14,7 +14,7 @@ from plinth import kvstore, network from plinth.modules import first_boot, networks from .forms import (ConnectionTypeSelectForm, EthernetForm, GenericForm, - InternetConnectionTypeForm, PPPoEForm, + InternetConnectionTypeForm, NetworkTopologyForm, PPPoEForm, RouterConfigurationForm, WifiForm) logger = logging.getLogger(__name__) @@ -406,6 +406,21 @@ def delete(request, uuid): }) +class NetworkTopologyView(FormView): + """View for local network topology form.""" + template_name = 'network_topology_update.html' + form_class = NetworkTopologyForm + success_url = reverse_lazy('networks:index') + + def get_initial(self): + """Get initial form data.""" + pass + + def form_valid(self, form): + """Save value to DB.""" + return super().form_valid(form) + + class RouterConfigurationView(FormView): """View for router configuration form.""" template_name = 'router_configuration_update.html' From 4dd1035cf3204ec084a4441db992d235b6ae644a Mon Sep 17 00:00:00 2001 From: Nektarios Katakis Date: Sat, 29 Feb 2020 05:36:20 +0000 Subject: [PATCH 26/41] networks: First boot view for network topology wizard Signed-off-by: Nektarios Katakis [sunil: Use the term 'network topology' consistently] Signed-off-by: Sunil Mohan Adapa Reviewed-by: Sunil Mohan Adapa --- .../templates/network_topology_firstboot.html | 24 +++++++++++++++++++ plinth/modules/networks/views.py | 17 +++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 plinth/modules/networks/templates/network_topology_firstboot.html diff --git a/plinth/modules/networks/templates/network_topology_firstboot.html b/plinth/modules/networks/templates/network_topology_firstboot.html new file mode 100644 index 000000000..4c3eafbb0 --- /dev/null +++ b/plinth/modules/networks/templates/network_topology_firstboot.html @@ -0,0 +1,24 @@ +{% extends "base_firstboot.html" %} +{% comment %} +# SPDX-License-Identifier: AGPL-3.0-or-later +{% endcomment %} + +{% load bootstrap %} +{% load i18n %} +{% load static %} + +{% block content %} + {% include "network_topology_content.html" %} + +
+ {% csrf_token %} + + {{ form|bootstrap }} + + + +
+ +{% endblock %} diff --git a/plinth/modules/networks/views.py b/plinth/modules/networks/views.py index 0b7ca5fd5..3a0472777 100644 --- a/plinth/modules/networks/views.py +++ b/plinth/modules/networks/views.py @@ -421,6 +421,23 @@ class NetworkTopologyView(FormView): return super().form_valid(form) +class NetworkTopologyFirstBootView(NetworkTopologyView): + """View for network topology form during first wizard.""" + template_name = 'network_topology_firstboot.html' + + def get_success_url(self): + """Return next fistboot step.""" + return reverse_lazy(first_boot.next_step()) + + def form_valid(self, form): + """Mark the first wizard step as done, save value and redirect.""" + first_boot.mark_step_done('network_topology_wizard') + if 'skip' in form.data: + return FormView.form_valid(self, form) + + return super().form_valid(form) + + class RouterConfigurationView(FormView): """View for router configuration form.""" template_name = 'router_configuration_update.html' From 5fd3e95bdf7af948cbdf43862a163b62324e7c9b Mon Sep 17 00:00:00 2001 From: Nektarios Katakis Date: Sat, 29 Feb 2020 05:37:29 +0000 Subject: [PATCH 27/41] networks: First boot step for network topology wizard Signed-off-by: Nektarios Katakis [sunil: Use the term 'network topology' consistently] Signed-off-by: Sunil Mohan Adapa Reviewed-by: Sunil Mohan Adapa --- plinth/modules/networks/__init__.py | 5 +++++ plinth/modules/networks/urls.py | 3 +++ 2 files changed, 8 insertions(+) diff --git a/plinth/modules/networks/__init__.py b/plinth/modules/networks/__init__.py index 74005b15e..48f5f73ea 100644 --- a/plinth/modules/networks/__init__.py +++ b/plinth/modules/networks/__init__.py @@ -19,6 +19,11 @@ is_essential = True managed_packages = ['network-manager', 'batctl'] first_boot_steps = [ + { + 'id': 'network_topology_wizard', + 'url': 'networks:network-topology-first-boot', + 'order': 2, + }, { 'id': 'internet_connectivity_type_wizard', 'url': 'networks:internet-connection-type-first-boot', diff --git a/plinth/modules/networks/urls.py b/plinth/modules/networks/urls.py index 873a5e51e..db6629d66 100644 --- a/plinth/modules/networks/urls.py +++ b/plinth/modules/networks/urls.py @@ -39,4 +39,7 @@ urlpatterns = [ name='internet-connection-type-first-boot'), url(r'^sys/networks/network-topology/$', views.NetworkTopologyView.as_view(), name='network-topology'), + url(r'^sys/networks/firstboot/network-topology-first-boot/$', + views.NetworkTopologyFirstBootView.as_view(), + name='network-topology-first-boot'), ] From 2a00b186ea79195663679450876fdadb6eda44cb Mon Sep 17 00:00:00 2001 From: Nektarios Katakis Date: Sat, 29 Feb 2020 05:49:28 +0000 Subject: [PATCH 28/41] networks: Save networks topology type to DB Signed-off-by: Nektarios Katakis [sunil: Use the term 'network topology' consistently] Signed-off-by: Sunil Mohan Adapa Reviewed-by: Sunil Mohan Adapa --- plinth/modules/networks/__init__.py | 1 + plinth/modules/networks/views.py | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/plinth/modules/networks/__init__.py b/plinth/modules/networks/__init__.py index 48f5f73ea..7966e7328 100644 --- a/plinth/modules/networks/__init__.py +++ b/plinth/modules/networks/__init__.py @@ -47,6 +47,7 @@ logger = Logger(__name__) app = None +NETWORK_TOPOLOGY_TYPE_KEY = 'networks_topology_type' ROUTER_CONFIGURATION_TYPE_KEY = 'networks_router_configuration_type' INTERNET_CONNECTION_TYPE_KEY = 'networks_internet_type' diff --git a/plinth/modules/networks/views.py b/plinth/modules/networks/views.py index 3a0472777..f1c4ce0f1 100644 --- a/plinth/modules/networks/views.py +++ b/plinth/modules/networks/views.py @@ -414,10 +414,18 @@ class NetworkTopologyView(FormView): def get_initial(self): """Get initial form data.""" - pass + return { + 'network_topology': + kvstore.get_default(networks.NETWORK_TOPOLOGY_TYPE_KEY, + 'to_router') + } def form_valid(self, form): """Save value to DB.""" + network_topology = form.cleaned_data['network_topology'] + logger.info('Updating network topology type with value %s' % + network_topology) + kvstore.set(networks.NETWORK_TOPOLOGY_TYPE_KEY, network_topology) return super().form_valid(form) From 06664e148911faee8f0bcb89235c9f267d522d9b Mon Sep 17 00:00:00 2001 From: Nektarios Katakis Date: Sat, 29 Feb 2020 06:12:46 +0000 Subject: [PATCH 29/41] networks: Update main networks page Internet connectivity section Closes: #1555 Signed-off-by: Nektarios Katakis [sunil: Use the term 'network topology' consistently] [sunil: s/Router/router in template] Signed-off-by: Sunil Mohan Adapa Reviewed-by: Sunil Mohan Adapa --- .../templates/network_topology_main.html | 43 +++++++++++++++++++ .../templates/networks_configuration.html | 2 +- .../templates/router_configuration_main.html | 31 ------------- plinth/modules/networks/views.py | 8 +++- 4 files changed, 51 insertions(+), 33 deletions(-) create mode 100644 plinth/modules/networks/templates/network_topology_main.html delete mode 100644 plinth/modules/networks/templates/router_configuration_main.html diff --git a/plinth/modules/networks/templates/network_topology_main.html b/plinth/modules/networks/templates/network_topology_main.html new file mode 100644 index 000000000..731884da0 --- /dev/null +++ b/plinth/modules/networks/templates/network_topology_main.html @@ -0,0 +1,43 @@ +{% comment %} +# SPDX-License-Identifier: AGPL-3.0-or-later +{% endcomment %} + +{% load bootstrap %} +{% load i18n %} + +

+ {% blocktrans trimmed %} + {{ box_name }} Internet Connectivity + {% endblocktrans %} +

+ +

+ {% blocktrans trimmed %} + The following best describes how your {{ box_name }} is connected in your + network. This information is used only to suggest necessary configuration + actions. + {% endblocktrans %} +

+ +

+ {% if network_topology == "to_router" %} + {% blocktrans trimmed %} + Your {{ box_name }} gets its Internet connection from your router via Wi-Fi + or Ethernet cable. This is a typical home setup. + {% endblocktrans %} + {% elif network_topology == "as_router" %} + {% blocktrans trimmed %} + Your {{ box_name }} is directly connected to the Internet and all your + devices connect to {{ box_name }} for their Internet connectivity. + {% endblocktrans %} + {% else %} + {% blocktrans trimmed %} + Your Internet connection is directly attached to your {{ box_name }} and there + are no other devices on the network. + {% endblocktrans %} + {% endif %} + + {% trans 'Update...' %} + +

diff --git a/plinth/modules/networks/templates/networks_configuration.html b/plinth/modules/networks/templates/networks_configuration.html index 01d7c7b30..5da805ef8 100644 --- a/plinth/modules/networks/templates/networks_configuration.html +++ b/plinth/modules/networks/templates/networks_configuration.html @@ -42,7 +42,7 @@ {% block configuration %} {% include "connections_list.html" %} - {% include "router_configuration_main.html" %} + {% include "network_topology_main.html" %} {% include "internet_connectivity_main.html" %} {% endblock %} diff --git a/plinth/modules/networks/templates/router_configuration_main.html b/plinth/modules/networks/templates/router_configuration_main.html deleted file mode 100644 index b8c4369ed..000000000 --- a/plinth/modules/networks/templates/router_configuration_main.html +++ /dev/null @@ -1,31 +0,0 @@ -{% comment %} -# SPDX-License-Identifier: AGPL-3.0-or-later -{% endcomment %} - -{% load bootstrap %} -{% load i18n %} - -

- {% blocktrans trimmed %} - {{ box_name }} Internet Connectivity - {% endblocktrans %} -

- -

- {% blocktrans trimmed %} - The following best describes how your {{ box_name }} is connected in your - network. This information is used only to suggest necessary configuration - actions. - {% endblocktrans %} -

- -

- {% blocktrans trimmed %} - Your {{ box_name }} gets its Internet from your Router via Wi-Fi or - Ethernet cable. This is a typical home setup. - {% endblocktrans %} - - {% trans 'Update...' %} - -

diff --git a/plinth/modules/networks/views.py b/plinth/modules/networks/views.py index f1c4ce0f1..3d55fbd35 100644 --- a/plinth/modules/networks/views.py +++ b/plinth/modules/networks/views.py @@ -24,6 +24,8 @@ def index(request): """Show connection list.""" connections = network.get_connection_list() + network_topology = kvstore.get_default(networks.NETWORK_TOPOLOGY_TYPE_KEY, + 'to_router') internet_connection_type = kvstore.get_default( networks.INTERNET_CONNECTION_TYPE_KEY, 'unknown') return TemplateResponse( @@ -34,7 +36,8 @@ def index(request): 'has_diagnostics': True, 'is_enabled': True, 'connections': connections, - 'internet_connectivity_type': internet_connection_type + 'network_topology': network_topology, + 'internet_connectivity_type': internet_connection_type, }) @@ -426,6 +429,9 @@ class NetworkTopologyView(FormView): logger.info('Updating network topology type with value %s' % network_topology) kvstore.set(networks.NETWORK_TOPOLOGY_TYPE_KEY, network_topology) + if network_topology == 'to_router': + self.success_url = reverse_lazy('networks:router-configuration') + return super().form_valid(form) From 8a93b5191f4edfa64297cdb7f0d14eed71a08a2c Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Fri, 6 Mar 2020 13:43:08 -0800 Subject: [PATCH 30/41] networks: Show router wizard before Internet connection type wizard After user selects that they are behind the router, we need to show the router configuration wizard step. Only after this should be show the Internet connection type step. Signed-off-by: Sunil Mohan Adapa --- plinth/modules/networks/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plinth/modules/networks/__init__.py b/plinth/modules/networks/__init__.py index 7966e7328..36409eea4 100644 --- a/plinth/modules/networks/__init__.py +++ b/plinth/modules/networks/__init__.py @@ -25,13 +25,13 @@ first_boot_steps = [ 'order': 2, }, { - 'id': 'internet_connectivity_type_wizard', - 'url': 'networks:internet-connection-type-first-boot', + 'id': 'router_setup_wizard', + 'url': 'networks:router-configuration-first-boot', 'order': 3, }, { - 'id': 'router_setup_wizard', - 'url': 'networks:router-configuration-first-boot', + 'id': 'internet_connectivity_type_wizard', + 'url': 'networks:internet-connection-type-first-boot', 'order': 4, }, ] From ba6f461ece1b36f92b034d88215d948dc5530e78 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Fri, 6 Mar 2020 13:43:48 -0800 Subject: [PATCH 31/41] networks: Don't show router wizard if not behind a router If during the first wizard, the user selects that they are not behind a router, then don't show the router configuration wizard. Signed-off-by: Sunil Mohan Adapa --- plinth/modules/networks/views.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/plinth/modules/networks/views.py b/plinth/modules/networks/views.py index 3d55fbd35..6c66e01c8 100644 --- a/plinth/modules/networks/views.py +++ b/plinth/modules/networks/views.py @@ -3,6 +3,7 @@ import logging from django.contrib import messages +from django.http import HttpResponseRedirect from django.shortcuts import redirect from django.template.response import TemplateResponse from django.urls import reverse_lazy @@ -478,6 +479,16 @@ class RouterConfigurationFirstBootView(RouterConfigurationView): """View for router configuration form during first wizard.""" template_name = 'router_configuration_firstboot.html' + def dispatch(self, request, *args, **kwargs): + """Don't show wizard step if FreedomBox is not behind a router.""" + network_topology = kvstore.get_default( + networks.NETWORK_TOPOLOGY_TYPE_KEY, 'to_router') + if network_topology != 'to_router': + first_boot.mark_step_done('router_setup_wizard') + return HttpResponseRedirect(reverse_lazy(first_boot.next_step())) + + return super().dispatch(request, *args, *kwargs) + def get_success_url(self): """Return the next wizard step after this one.""" return reverse_lazy(first_boot.next_step()) From 2238352e45d43d9b7e532c231da479a8362b5b92 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Fri, 6 Mar 2020 14:08:29 -0800 Subject: [PATCH 32/41] networks: If topology wizard is skipped, skip router wizard too If the user chooses to skip the network topology wizard, then there is no need to show the router configuration wizard step. Skip it. We may want to skip other wizard step too. However, those can be dealt later. Signed-off-by: Sunil Mohan Adapa --- plinth/modules/networks/views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plinth/modules/networks/views.py b/plinth/modules/networks/views.py index 6c66e01c8..ace417ada 100644 --- a/plinth/modules/networks/views.py +++ b/plinth/modules/networks/views.py @@ -448,6 +448,7 @@ class NetworkTopologyFirstBootView(NetworkTopologyView): """Mark the first wizard step as done, save value and redirect.""" first_boot.mark_step_done('network_topology_wizard') if 'skip' in form.data: + first_boot.mark_step_done('router_setup_wizard') return FormView.form_valid(self, form) return super().form_valid(form) From 296f6dbe850889684fc39e9fa71b0c780ab9e87a Mon Sep 17 00:00:00 2001 From: Veiko Aasa Date: Fri, 6 Mar 2020 17:56:40 +0200 Subject: [PATCH 33/41] i2p: New style app page layout Get rid of tabs in the app page. Tests performed: - enable/disable app - check that links to the external site work - check that links to the external site are disabled if app is disabled - i2p functional tests pass Signed-off-by: Veiko Aasa --- plinth/modules/i2p/templates/i2p.html | 31 +++++--- plinth/modules/i2p/templates/i2p_service.html | 19 ----- plinth/modules/i2p/urls.py | 8 +-- plinth/modules/i2p/views.py | 72 ++++--------------- 4 files changed, 36 insertions(+), 94 deletions(-) delete mode 100644 plinth/modules/i2p/templates/i2p_service.html diff --git a/plinth/modules/i2p/templates/i2p.html b/plinth/modules/i2p/templates/i2p.html index 4f47d0a5b..f26901881 100644 --- a/plinth/modules/i2p/templates/i2p.html +++ b/plinth/modules/i2p/templates/i2p.html @@ -7,16 +7,31 @@ {% load i18n %} {% block configuration %} + {{ block.super }} -

{% trans "Configuration" %}

+

{% trans "I2P Proxies and Tunnels" %}

+ {% for line in proxies_description %} +

{{ line|safe }}

+ {% endfor %} -
- {% csrf_token %} +

+ + {% trans "Launch" %} + +

- {{ form|bootstrap }} - - -
+

{% trans "Anonymous Torrents" %}

+ {% for line in torrents_description %} +

{{ line|safe }}

+ {% endfor %} +

+ + {% trans "Launch" %} + +

{% endblock %} diff --git a/plinth/modules/i2p/templates/i2p_service.html b/plinth/modules/i2p/templates/i2p_service.html deleted file mode 100644 index 468a063d5..000000000 --- a/plinth/modules/i2p/templates/i2p_service.html +++ /dev/null @@ -1,19 +0,0 @@ -{% extends "app.html" %} -{% comment %} -# SPDX-License-Identifier: AGPL-3.0-or-later -{% endcomment %} - -{% load i18n %} - -{% block configuration %} - {% for line in service_description %} -

{{ line|safe }}

- {% endfor %} - -

- - {% trans "Launch" %} - -

-{% endblock %} diff --git a/plinth/modules/i2p/urls.py b/plinth/modules/i2p/urls.py index fd3b7167d..cab9dcb84 100644 --- a/plinth/modules/i2p/urls.py +++ b/plinth/modules/i2p/urls.py @@ -4,12 +4,6 @@ URLs for the I2P module. """ from django.conf.urls import url - from plinth.modules.i2p import views -urlpatterns = [ - url(r'^apps/i2p/$', views.I2PAppView.as_view(), name='index'), - url(r'^apps/i2p/tunnels/?$', views.TunnelsView.as_view(), name='tunnels'), - url(r'^apps/i2p/torrents/?$', views.TorrentsView.as_view(), - name='torrents'), -] +urlpatterns = [url(r'^apps/i2p/$', views.I2PAppView.as_view(), name='index')] diff --git a/plinth/modules/i2p/views.py b/plinth/modules/i2p/views.py index a809f113d..c5b3bfb56 100644 --- a/plinth/modules/i2p/views.py +++ b/plinth/modules/i2p/views.py @@ -3,66 +3,16 @@ Views for I2P application. """ -from django.urls import reverse_lazy from django.utils.translation import ugettext as _ -from django.utils.translation import ugettext_lazy -from django.views.generic import TemplateView - -import plinth.modules.i2p as i2p +from plinth.modules import i2p from plinth.views import AppView -subsubmenu = [{ - 'url': reverse_lazy('i2p:index'), - 'text': ugettext_lazy('Configure') -}, { - 'url': reverse_lazy('i2p:tunnels'), - 'text': ugettext_lazy('Proxies') -}, { - 'url': reverse_lazy('i2p:torrents'), - 'text': ugettext_lazy('Anonymous torrents') -}] - class I2PAppView(AppView): """Serve configuration page.""" app_id = 'i2p' template_name = 'i2p.html' - - def get_context_data(self, **kwargs): - """Return the context data for rendering the template view.""" - context = super().get_context_data(**kwargs) - context['title'] = i2p.app.info.name - context['app_info'] = i2p.app.info - context['subsubmenu'] = subsubmenu - context['port_forwarding_info'] = i2p.port_forwarding_info - return context - - -class ServiceBaseView(TemplateView): - """View to describe and launch a service.""" - service_description = None - service_title = None - service_path = None - - def get_context_data(self, **kwargs): - """Add context data for template.""" - context = super().get_context_data(**kwargs) - context['title'] = i2p.app.info.name - context['app_info'] = i2p.app.info - context['subsubmenu'] = subsubmenu - context['is_enabled'] = i2p.app.is_enabled() - context['service_title'] = self.service_title - context['service_path'] = self.service_path - context['service_description'] = self.service_description - return context - - -class TunnelsView(ServiceBaseView): - """View to describe and launch tunnel configuration.""" - template_name = 'i2p_service.html' - service_title = _('I2P Proxies and Tunnels') - service_path = '/i2p/i2ptunnel/' - service_description = [ + proxies_description = [ _('I2P lets you browse the Internet and hidden services (eepsites) ' 'anonymously. For this, your browser, preferably a Tor Browser, ' 'needs to be configured for a proxy.'), @@ -70,15 +20,17 @@ class TunnelsView(ServiceBaseView): 'proxies and tunnels may be configured using the tunnel ' 'configuration interface.'), ] - - -class TorrentsView(ServiceBaseView): - """View to describe and launch I2P torrents application.""" - template_name = 'i2p_service.html' - service_title = _('Anonymous Torrents') - service_path = '/i2p/i2psnark/' - service_description = [ + torrents_description = [ _('I2P provides an application to download files anonymously in a ' 'peer-to-peer network. Download files by adding torrents or ' 'create a new torrent to share a file.'), ] + + def get_context_data(self, **kwargs): + """Return the context data for rendering the template view.""" + context = super().get_context_data(**kwargs) + context['port_forwarding_info'] = i2p.port_forwarding_info + context['proxies_description'] = self.proxies_description + context['torrents_description'] = self.torrents_description + + return context From 2ed47b047d2323520709dfdbc2ecff9279aaab0e Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Wed, 4 Mar 2020 16:36:54 -0800 Subject: [PATCH 34/41] apache: Handle transition to php 7.4 Directory /etc/php/7.4 became available before php7.4-fpm became available. Handle this by checking the run time socket of the fpm daemon instead of the directory. Discussed and tested in https://discuss.freedombox.org/t/mediawiki-service-unavailable/711/23 Signed-off-by: Sunil Mohan Adapa Reviewed-by: James Valleroy --- .../conf-available/php-fpm-freedombox.conf | 34 ++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/plinth/modules/apache/data/etc/apache2/conf-available/php-fpm-freedombox.conf b/plinth/modules/apache/data/etc/apache2/conf-available/php-fpm-freedombox.conf index 80c6ca636..bbc4685cd 100644 --- a/plinth/modules/apache/data/etc/apache2/conf-available/php-fpm-freedombox.conf +++ b/plinth/modules/apache/data/etc/apache2/conf-available/php-fpm-freedombox.conf @@ -14,30 +14,18 @@ - - SetHandler "proxy:unix:/run/php/php7.3-fpm.sock|fcgi://localhost" - - + + SetHandler "proxy:unix:/run/php/php-fpm.sock|fcgi://localhost" + + SetHandler "proxy:unix:/run/php/php7.4-fpm.sock|fcgi://localhost" - - - SetHandler "proxy:unix:/run/php/php7.5-fpm.sock|fcgi://localhost" - - - SetHandler "proxy:unix:/run/php/php7.6-fpm.sock|fcgi://localhost" - - - SetHandler "proxy:unix:/run/php/php8.0-fpm.sock|fcgi://localhost" - - - SetHandler "proxy:unix:/run/php/php8.1-fpm.sock|fcgi://localhost" - - - SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost" - - - SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost" - + + + SetHandler "proxy:unix:/run/php/php7.3-fpm.sock|fcgi://localhost" + + + Require all denied + # Deny access to raw php sources by default From a673c06b591511777554d88270f9fcb6bd87054d Mon Sep 17 00:00:00 2001 From: Michael Breidenbach Date: Sat, 7 Mar 2020 05:16:54 +0000 Subject: [PATCH 35/41] Translated using Weblate (Swedish) Currently translated at 98.8% (1251 of 1265 strings) --- plinth/locale/sv/LC_MESSAGES/django.po | 62 ++++++++++++++------------ 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/plinth/locale/sv/LC_MESSAGES/django.po b/plinth/locale/sv/LC_MESSAGES/django.po index f3a335fef..3feb171f8 100644 --- a/plinth/locale/sv/LC_MESSAGES/django.po +++ b/plinth/locale/sv/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-02-24 19:12-0500\n" -"PO-Revision-Date: 2020-02-24 21:32+0000\n" +"PO-Revision-Date: 2020-03-08 17:32+0000\n" "Last-Translator: Michael Breidenbach \n" "Language-Team: Swedish \n" @@ -643,10 +643,8 @@ msgid "Enable Domain Name System Security Extensions" msgstr "Aktivera Domain Name System Security Extensions" #: plinth/modules/bind/templates/bind.html:11 -#, fuzzy -#| msgid "Server domain" msgid "Serving Domains" -msgstr "Server-domän" +msgstr "Betjäna domäner" #: plinth/modules/bind/templates/bind.html:16 #: plinth/modules/ikiwiki/forms.py:12 @@ -656,27 +654,21 @@ msgid "Type" msgstr "Typ" #: plinth/modules/bind/templates/bind.html:17 -#, fuzzy -#| msgid "Domain Name" msgid "Domain Names" msgstr "Domännamn" #: plinth/modules/bind/templates/bind.html:18 -#, fuzzy -#| msgid "Service" msgid "Serving" -msgstr "Tjänst" +msgstr "Servering" #: plinth/modules/bind/templates/bind.html:19 -#, fuzzy -#| msgid "IP address" msgid "IP addresses" -msgstr "IP-adress" +msgstr "IP-adresser" #: plinth/modules/bind/templates/bind.html:35 #: plinth/modules/bind/templates/bind.html:37 msgid "Refresh IP address and domains" -msgstr "" +msgstr "Uppdatera IP-adress och domäner" #: plinth/modules/bind/views.py:73 plinth/modules/deluge/views.py:46 #: plinth/modules/dynamicdns/views.py:150 plinth/modules/openvpn/views.py:134 @@ -3515,7 +3507,7 @@ msgstr "Öppet" #: plinth/modules/networks/forms.py:297 msgid "Choose your internet connection type" -msgstr "" +msgstr "Välj din internetanslutningstyp" #: plinth/modules/networks/forms.py:301 msgid "" @@ -3527,6 +3519,13 @@ msgid "" "connectivity. If you have a public IP address but are unsure if it changes " "over time or not, it is safer to choose this option.

" msgstr "" +"Jag har en offentlig IP-adress som kan ändras med tiden

Det innebär att enheter på Internet kan nå dig när du är ansluten " +"till Internet. Varje gång du ansluter till Internet med Internet-" +"leverantören kan du få en annan IP-adress, särskilt efter lite offlinetid. " +"Många Internetleverantörer erbjuder den här typen av anslutning. Om du har " +"en offentlig IP-adress men är osäker på om den ändras med tiden eller inte, " +"är det säkrare att välja det här alternativet.

" #: plinth/modules/networks/forms.py:313 #, python-brace-format @@ -3539,6 +3538,13 @@ msgid "" "but very few ISPs offer this. You may be able to get this service from your " "ISP by making an additional payment.

" msgstr "" +"Jag har en offentlig IP-adress som inte ändrar övertid (rekommenderas)

Det innebär att enheter på Internet kan nå dig när du " +"är ansluten till Internet. Varje gång du ansluter till Internet med Internet-" +"leverantören får du alltid samma IP-adress. Detta är den mest problemfria " +"installationen för många {box_name} tjänster men mycket få " +"Internetleverantörer erbjuder detta. Du kanske kan få den här tjänsten från " +"internetleverantören genom att göra en extra betalning.

" #: plinth/modules/networks/forms.py:326 #, python-brace-format @@ -3551,20 +3557,20 @@ msgid "" "troublesome situation for hosting services at home. {box_name} provides many " "workaround solutions but each solution has some limitations.

" msgstr "" +"Jag har ingen offentlig IP-adress

Det innebär att " +"enheter på Internet inte kan nå dig när du är ansluten till " +"Internet. Varje gång du ansluter till Internet med Internet-leverantören får " +"du en IP-adress som endast är relevant för lokala nätverk. Många " +"Internetleverantörer erbjuder den här typen av anslutning. Detta är den mest " +"besvärliga situationen för hosting tjänster hemma. {box_name} innehåller " +"många lösningar men varje lösning har vissa begränsningar.

" #: plinth/modules/networks/forms.py:351 msgid "Preferred router configuration" msgstr "Önskad routerkonfiguration" #: plinth/modules/networks/forms.py:356 -#, fuzzy, python-brace-format -#| msgid "" -#| "Use DMZ feature to forward all traffic

Most " -#| "routers provide a configuration setting called DMZ. This will allow the " -#| "router to forward all incoming traffic from the internet to a single IP " -#| "address such as the {box_name}'s address. First remember to configure a " -#| "static local IP address for your {box_name} in your router's " -#| "configuration.

" +#, python-brace-format msgid "" "Use DMZ feature to forward all traffic (recommended)

Most routers provide a configuration setting called DMZ. This will allow " @@ -3573,12 +3579,12 @@ msgid "" "static local IP address for your {box_name} in your router's configuration." msgstr "" -"Använd DMZ-funktionen för att vidarebefordra all trafik

De flesta routrar tillhandahåller en konfigurationsinställning som kallas " -"DMZ. Detta gör det möjligt för routern att vidarebefordra all inkommande " -"trafik från Internet till en enda IP-adress, till exempel {box_name}-" -"adressen. Kom först ihåg att konfigurera en statisk lokal IP-adress för din " -"{box_name} i routerns configuration.

" +"Använd DMZ-funktionen för att vidarebefordra all trafik

De flesta routrar tillhandahåller en konfigurationsinställning som " +"kallas DMZ. Detta gör det möjligt för routern att vidarebefordra all " +"inkommande trafik från Internet till en enda IP-adress, till exempel " +"{box_name}-adressen. Kom först ihåg att konfigurera en statisk lokal IP-" +"adress för din {box_name} i routerns konfiguration.

" #: plinth/modules/networks/forms.py:368 #, fuzzy, python-brace-format From 53bf6e28a6c00843b67591caa049aa76b17ca02e Mon Sep 17 00:00:00 2001 From: James Valleroy Date: Sun, 8 Mar 2020 16:04:31 -0400 Subject: [PATCH 36/41] ci: Switch to testing image Signed-off-by: James Valleroy Reviewed-by: Sunil Mohan Adapa --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ff5bbea51..531950364 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: debian:unstable +image: debian:testing before_script: - export DEBIAN_FRONTEND=noninteractive From 0c1591324d8652f67c076a52e1a532b42b78c299 Mon Sep 17 00:00:00 2001 From: Veiko Aasa Date: Wed, 26 Feb 2020 11:47:08 +0200 Subject: [PATCH 37/41] quassel: Fix unable to disable application without choosing a domain name Closes #1700 Signed-off-by: Veiko Aasa Reviewed-by: James Valleroy --- plinth/modules/quassel/forms.py | 1 + plinth/modules/quassel/views.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/plinth/modules/quassel/forms.py b/plinth/modules/quassel/forms.py index 723f7338e..76c75b357 100644 --- a/plinth/modules/quassel/forms.py +++ b/plinth/modules/quassel/forms.py @@ -24,4 +24,5 @@ class QuasselForm(AppForm): help_text=_( 'Select a domain to use TLS with. If the list is empty, please ' 'configure at least one domain with certificates.'), + required=False, ) diff --git a/plinth/modules/quassel/views.py b/plinth/modules/quassel/views.py index bf7337f03..cad5ed3de 100644 --- a/plinth/modules/quassel/views.py +++ b/plinth/modules/quassel/views.py @@ -20,7 +20,9 @@ class QuasselAppView(AppView): def form_valid(self, form): """Change the access control of Radicale service.""" data = form.cleaned_data - if quassel.get_domain() != data['domain']: + app_disable = form.initial['is_enabled'] and not data['is_enabled'] + + if not app_disable and quassel.get_domain() != data['domain']: quassel.set_domain(data['domain']) quassel.app.get_component( 'letsencrypt-quassel').setup_certificates() From 50e5608331330b37c0b9cce846e34ccc193d1b0d Mon Sep 17 00:00:00 2001 From: Joseph Nuthalapati Date: Wed, 26 Feb 2020 21:44:42 +0530 Subject: [PATCH 38/41] shadowsocks: Move user settings to state directory Fixes #1775 Signed-off-by: Joseph Nuthalapati Reviewed-by: James Valleroy --- actions/shadowsocks | 40 +++++++++++++------ plinth/modules/shadowsocks/__init__.py | 7 +++- .../freedombox.conf | 2 + plinth/modules/shadowsocks/manifest.py | 4 +- 4 files changed, 38 insertions(+), 15 deletions(-) create mode 100644 plinth/modules/shadowsocks/data/lib/systemd/system/shadowsocks-libev-local@.service.d/freedombox.conf diff --git a/actions/shadowsocks b/actions/shadowsocks index 1ade9ec33..21ebc62d1 100755 --- a/actions/shadowsocks +++ b/actions/shadowsocks @@ -7,12 +7,15 @@ Helper script for configuring Shadowsocks. import argparse import json import os +import subprocess import sys from plinth import action_utils from plinth.modules import shadowsocks -SHADOWSOCKS_CONFIG = '/etc/shadowsocks-libev/freedombox.json' +SHADOWSOCKS_CONFIG_SYMLINK = '/etc/shadowsocks-libev/freedombox.json' +SHADOWSOCKS_CONFIG_ACTUAL = \ + '/var/lib/private/shadowsocks-libev/freedombox/freedombox.json' def parse_arguments(): @@ -26,6 +29,11 @@ def parse_arguments(): subparsers.add_parser('merge-config', help='Merge JSON config from stdin with existing') + # Migrations + subparsers.add_parser( + 'migrate-1-2', + help='Move shadowsocks config file to a secure location') + subparsers.required = True return parser.parse_args() @@ -35,23 +43,25 @@ def subcommand_setup(_): # Only client socks5 proxy is supported for now. Disable the # server component. action_utils.service_disable('shadowsocks-libev') + if not os.path.islink(SHADOWSOCKS_CONFIG_SYMLINK): + os.symlink(SHADOWSOCKS_CONFIG_ACTUAL, SHADOWSOCKS_CONFIG_SYMLINK) -def subcommand_get_config(arguments): +def subcommand_get_config(_): """Read and print Shadowsocks configuration.""" try: - print(open(SHADOWSOCKS_CONFIG, 'r').read()) + print(open(SHADOWSOCKS_CONFIG_SYMLINK, 'r').read()) except Exception: sys.exit(1) -def subcommand_merge_config(arguments): +def subcommand_merge_config(_): """Configure Shadowsocks.""" config = sys.stdin.read() config = json.loads(config) try: - current_config = open(SHADOWSOCKS_CONFIG, 'r').read() + current_config = open(SHADOWSOCKS_CONFIG_SYMLINK, 'r').read() current_config = json.loads(current_config) except (OSError, json.JSONDecodeError): current_config = {} @@ -59,16 +69,20 @@ def subcommand_merge_config(arguments): new_config = current_config new_config.update(config) new_config = json.dumps(new_config, indent=4, sort_keys=True) + open(SHADOWSOCKS_CONFIG_SYMLINK, 'w').write(new_config) - # XXX: Config file with password is world-readable. This is the - # same as the default config file, but find a way to avoid this. - # See https://salsa.debian.org/freedombox-team/plinth/-/merge_requests/1724 - old_umask = os.umask(0o022) - try: - open(SHADOWSOCKS_CONFIG, 'w').write(new_config) - finally: - os.umask(old_umask) + action_utils.service_restart(shadowsocks.managed_services[0]) + +def subcommand_migrate_1_2(_): + """Move shadowsocks config file to a secure location.""" + if os.path.isfile(SHADOWSOCKS_CONFIG_SYMLINK): # ignoring symlinks + os.makedirs('/var/lib/private/shadowsocks-libev/freedombox/', + exist_ok=True) + os.replace(SHADOWSOCKS_CONFIG_SYMLINK, SHADOWSOCKS_CONFIG_ACTUAL) + os.symlink(SHADOWSOCKS_CONFIG_ACTUAL, SHADOWSOCKS_CONFIG_SYMLINK) + + subprocess.check_call(['systemctl', 'daemon-reload']) action_utils.service_restart(shadowsocks.managed_services[0]) diff --git a/plinth/modules/shadowsocks/__init__.py b/plinth/modules/shadowsocks/__init__.py index 531394475..773749333 100644 --- a/plinth/modules/shadowsocks/__init__.py +++ b/plinth/modules/shadowsocks/__init__.py @@ -15,7 +15,7 @@ from plinth.utils import format_lazy from .manifest import backup # noqa, pylint: disable=unused-import -version = 1 +version = 2 managed_services = ['shadowsocks-libev-local@freedombox'] @@ -89,6 +89,11 @@ def init(): def setup(helper, old_version=None): """Install and configure the module.""" + + if old_version == 1: + helper.call('migration', actions.superuser_run, 'shadowsocks', + ['migrate-1-2']) + helper.install(managed_packages) helper.call('post', actions.superuser_run, 'shadowsocks', ['setup']) helper.call('post', app.enable) diff --git a/plinth/modules/shadowsocks/data/lib/systemd/system/shadowsocks-libev-local@.service.d/freedombox.conf b/plinth/modules/shadowsocks/data/lib/systemd/system/shadowsocks-libev-local@.service.d/freedombox.conf new file mode 100644 index 000000000..ef74f9383 --- /dev/null +++ b/plinth/modules/shadowsocks/data/lib/systemd/system/shadowsocks-libev-local@.service.d/freedombox.conf @@ -0,0 +1,2 @@ +[Service] +StateDirectory=shadowsocks-libev/%i diff --git a/plinth/modules/shadowsocks/manifest.py b/plinth/modules/shadowsocks/manifest.py index 78a3455c6..38a0412cb 100644 --- a/plinth/modules/shadowsocks/manifest.py +++ b/plinth/modules/shadowsocks/manifest.py @@ -7,7 +7,9 @@ from plinth.modules.backups.api import validate as validate_backup backup = validate_backup({ 'secrets': { - 'files': ['/etc/shadowsocks-libev/freedombox.json'] + 'files': [ + '/var/lib/private/shadowsocks-libev/freedombox/freedombox.json' + ] }, 'services': ['shadowsocks-libev-local@freedombox'] }) From ef9068a42d3c1037a0edc64836be3cdca8001cc7 Mon Sep 17 00:00:00 2001 From: James Valleroy Date: Mon, 9 Mar 2020 19:15:43 -0400 Subject: [PATCH 39/41] locale: Update translation strings Signed-off-by: James Valleroy --- plinth/locale/bg/LC_MESSAGES/django.po | 696 +++++++++-------- plinth/locale/bn/LC_MESSAGES/django.po | 696 +++++++++-------- plinth/locale/cs/LC_MESSAGES/django.po | 747 ++++++++++-------- plinth/locale/da/LC_MESSAGES/django.po | 746 ++++++++++-------- plinth/locale/de/LC_MESSAGES/django.po | 781 +++++++++++-------- plinth/locale/django.pot | 696 +++++++++-------- plinth/locale/el/LC_MESSAGES/django.po | 746 ++++++++++-------- plinth/locale/es/LC_MESSAGES/django.po | 778 +++++++++++-------- plinth/locale/fa/LC_MESSAGES/django.po | 730 ++++++++++-------- plinth/locale/fake/LC_MESSAGES/django.po | 750 ++++++++++-------- plinth/locale/fr/LC_MESSAGES/django.po | 791 +++++++++++-------- plinth/locale/gl/LC_MESSAGES/django.po | 696 +++++++++-------- plinth/locale/gu/LC_MESSAGES/django.po | 724 ++++++++++-------- plinth/locale/hi/LC_MESSAGES/django.po | 741 ++++++++++-------- plinth/locale/hu/LC_MESSAGES/django.po | 746 ++++++++++-------- plinth/locale/id/LC_MESSAGES/django.po | 729 ++++++++++-------- plinth/locale/it/LC_MESSAGES/django.po | 749 ++++++++++-------- plinth/locale/ja/LC_MESSAGES/django.po | 696 +++++++++-------- plinth/locale/kn/LC_MESSAGES/django.po | 696 +++++++++-------- plinth/locale/lt/LC_MESSAGES/django.po | 696 +++++++++-------- plinth/locale/nb/LC_MESSAGES/django.po | 750 ++++++++++-------- plinth/locale/nl/LC_MESSAGES/django.po | 745 ++++++++++-------- plinth/locale/pl/LC_MESSAGES/django.po | 728 ++++++++++-------- plinth/locale/pt/LC_MESSAGES/django.po | 734 ++++++++++-------- plinth/locale/ru/LC_MESSAGES/django.po | 739 ++++++++++-------- plinth/locale/sl/LC_MESSAGES/django.po | 723 ++++++++++-------- plinth/locale/sv/LC_MESSAGES/django.po | 806 +++++++++++--------- plinth/locale/ta/LC_MESSAGES/django.po | 696 +++++++++-------- plinth/locale/te/LC_MESSAGES/django.po | 779 ++++++++++--------- plinth/locale/tr/LC_MESSAGES/django.po | 741 ++++++++++-------- plinth/locale/uk/LC_MESSAGES/django.po | 723 ++++++++++-------- plinth/locale/zh_Hans/LC_MESSAGES/django.po | 738 ++++++++++-------- 32 files changed, 13103 insertions(+), 10429 deletions(-) diff --git a/plinth/locale/bg/LC_MESSAGES/django.po b/plinth/locale/bg/LC_MESSAGES/django.po index 941b74df4..8b8dfcffe 100644 --- a/plinth/locale/bg/LC_MESSAGES/django.po +++ b/plinth/locale/bg/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-02-24 19:12-0500\n" +"POT-Creation-Date: 2020-03-09 19:13-0400\n" "PO-Revision-Date: 2019-10-12 14:52+0000\n" "Last-Translator: Nevena Mircheva \n" "Language-Team: Bulgarian