diff --git a/functional_tests/config.ini b/functional_tests/config.ini
index 047801387..77313c4e2 100644
--- a/functional_tests/config.ini
+++ b/functional_tests/config.ini
@@ -2,3 +2,4 @@
url = https://localhost:4430
username = tester
password = testingtesting
+delete_root_backup_archives = true
diff --git a/functional_tests/step_definitions/application.py b/functional_tests/step_definitions/application.py
index 417226953..49c1f82c5 100644
--- a/functional_tests/step_definitions/application.py
+++ b/functional_tests/step_definitions/application.py
@@ -221,12 +221,12 @@ def set_mediawiki_admin_password(browser, password):
@when(parsers.parse('I enable message archive management'))
-def set_mediawiki_admin_password(browser):
+def mediawiki_enable_archive_management(browser):
application.enable_ejabberd_message_archive_management(browser)
@when(parsers.parse('I disable message archive management'))
-def set_mediawiki_admin_password(browser):
+def mediawiki_disable_archive_management(browser):
application.disable_ejabberd_message_archive_management(browser)
diff --git a/functional_tests/step_definitions/system.py b/functional_tests/step_definitions/system.py
index 4142deba0..cc4405334 100644
--- a/functional_tests/step_definitions/system.py
+++ b/functional_tests/step_definitions/system.py
@@ -21,7 +21,7 @@ import time
from pytest import fixture
from pytest_bdd import given, parsers, then, when
-from support import system
+from support import config, system
language_codes = {
'Deutsch': 'de',
@@ -178,6 +178,8 @@ def dynamicdns_has_original_config(browser):
@when(parsers.parse('I create a backup of the {app_name:w} app data'))
def backup_create(browser, app_name):
+ if config.getboolean('DEFAULT', 'delete_root_backup_archives'):
+ system.backup_delete_root_archives(browser)
system.backup_create(browser, app_name)
diff --git a/functional_tests/support/system.py b/functional_tests/support/system.py
index 6576a8c16..0cb4bbd38 100644
--- a/functional_tests/support/system.py
+++ b/functional_tests/support/system.py
@@ -187,14 +187,20 @@ def dynamicdns_change_config(browser):
submit(browser)
+def backup_delete_root_archives(browser):
+ """Delete all archives of the root borg repository"""
+ browser.visit(default_url + '/plinth/sys/backups/')
+ path = "//a[starts-with(@href,'/plinth/sys/backups/delete/root/')]"
+ while browser.find_by_xpath(path):
+ browser.find_by_xpath(path).first.click()
+ with wait_for_page_update(browser,
+ expected_url='/plinth/sys/backups/'):
+ submit(browser)
+
+
def backup_create(browser, app_name):
browser.visit(default_url)
application.install(browser, 'backups')
- delete = browser.find_link_by_href(
- '/plinth/sys/backups/delete/root/_functional_test_' + app_name + '/')
- if delete:
- delete.first.click()
- submit(browser)
browser.find_link_by_href('/plinth/sys/backups/create/').first.click()
browser.find_by_id('id_backups-name').fill('_functional_test_' + app_name)
@@ -210,9 +216,9 @@ def backup_create(browser, app_name):
def backup_restore(browser, app_name):
browser.visit(default_url)
nav_to_module(browser, 'backups')
- browser.find_link_by_href(
- '/plinth/sys/backups/restore-archive/root/_functional_test_' +
- app_name + '/').first.click()
+ path = "//a[starts-with(@href,'/plinth/sys/backups/restore-archive/root/')]"
+ # assume that want to restore the last (most recently created) backup
+ browser.find_by_xpath(path).last.click()
with wait_for_page_update(browser, expected_url='/plinth/sys/backups/'):
submit(browser)
diff --git a/plinth/modules/backups/forms.py b/plinth/modules/backups/forms.py
index f58a224f4..f5c5b0c9f 100644
--- a/plinth/modules/backups/forms.py
+++ b/plinth/modules/backups/forms.py
@@ -19,12 +19,10 @@ Forms for backups module.
"""
from django import forms
-from django.core import validators
from django.core.validators import FileExtensionValidator
from django.utils.translation import ugettext, ugettext_lazy as _
from plinth.utils import format_lazy
-from plinth import cfg
from . import api, network_storage, ROOT_REPOSITORY_NAME
@@ -54,12 +52,6 @@ def _get_repository_choices():
class CreateArchiveForm(forms.Form):
repository = forms.ChoiceField()
- name = forms.CharField(
- label=_('Archive name'), strip=True,
- help_text=_('Name for new backup archive.'), validators=[
- validators.RegexValidator(r'^[^/]+$', _('Invalid archive name'))
- ])
-
selected_apps = forms.MultipleChoiceField(
label=_('Included apps'), help_text=_('Apps to include in the backup'),
widget=forms.CheckboxSelectMultiple)
@@ -98,7 +90,7 @@ class UploadForm(forms.Form):
class AddRepositoryForm(forms.Form):
repository = forms.CharField(
label=_('SSH Repository Path'), strip=True,
- help_text=_('Path of the new repository. Example: '
+ help_text=_('Path of a new or existing repository. Example: '
'user@host:~/path/to/repo/'))
ssh_password = forms.CharField(
label=_('SSH server password'), strip=True,
@@ -126,14 +118,6 @@ class AddRepositoryForm(forms.Form):
widget=forms.PasswordInput(),
required=False
)
- store_credentials = forms.BooleanField(
- label=_('Store passwords on FreedomBox'),
- help_text=format_lazy(
- _('Store the passwords on your {box_name}.'
- '
You need to store passwords if you want to run '
- 'recurrent backups.'), box_name=_(cfg.box_name)),
- required=False
- )
def clean(self):
cleaned_data = super(AddRepositoryForm, self).clean()
diff --git a/plinth/modules/backups/repository.py b/plinth/modules/backups/repository.py
index 997618281..a4ac753c3 100644
--- a/plinth/modules/backups/repository.py
+++ b/plinth/modules/backups/repository.py
@@ -233,12 +233,17 @@ class SshBorgRepository(BorgRepository):
return storage
def create_repository(self, encryption):
+ """Initialize / create a borg repository."""
if encryption not in SUPPORTED_BORG_ENCRYPTION:
raise ValueError('Unsupported encryption: %s' % encryption)
self._run('backups', ['init', '--path', self.path, '--encryption',
encryption])
def save(self, store_credentials=True):
+ """
+ Save the repository in network_storage (kvstore).
+ - store_credentials: Boolean whether credentials should be stored.
+ """
storage = self._get_network_storage_format(store_credentials)
self.uuid = network_storage.update_or_add(storage)
@@ -314,6 +319,7 @@ def get_ssh_repositories():
def get_repository(uuid):
+ """Get a repository (BorgRepository or SshBorgRepository)"""
if uuid == ROOT_REPOSITORY_UUID:
return BorgRepository(path=ROOT_REPOSITORY)
else:
diff --git a/plinth/modules/backups/views.py b/plinth/modules/backups/views.py
index 443afd4b4..19a519a3e 100644
--- a/plinth/modules/backups/views.py
+++ b/plinth/modules/backups/views.py
@@ -90,18 +90,11 @@ class CreateArchiveView(SuccessMessageMixin, FormView):
context['subsubmenu'] = subsubmenu
return context
- def get_initial(self):
- """Return the initial data to use for forms on this view."""
- initial = super().get_initial()
- initial['name'] = 'FreedomBox_backup_' + datetime.now().strftime(
- '%Y-%m-%d:%H:%M')
- return initial
-
def form_valid(self, form):
"""Create the archive on valid form submission."""
repository = get_repository(form.cleaned_data['repository'])
- repository.create_archive(form.cleaned_data['name'],
- form.cleaned_data['selected_apps'])
+ name = datetime.now().strftime('%Y-%m-%d:%H:%M')
+ repository.create_archive(name, form.cleaned_data['selected_apps'])
return super().form_valid(form)
@@ -293,8 +286,7 @@ class AddRepositoryView(SuccessMessageMixin, FormView):
repository.get_info()
except BorgRepositoryDoesNotExistError:
repository.create_repository(form.cleaned_data['encryption'])
- repository.save(
- store_credentials=form.cleaned_data['store_credentials'])
+ repository.save(store_credentials=True)
return super().form_valid(form)