diff --git a/src/vorta/assets/UI/mainwindow.ui b/src/vorta/assets/UI/mainwindow.ui
index 2e2950d7..a1916522 100644
--- a/src/vorta/assets/UI/mainwindow.ui
+++ b/src/vorta/assets/UI/mainwindow.ui
@@ -244,7 +244,7 @@
- true
+ false
diff --git a/src/vorta/borg/create.py b/src/vorta/borg/create.py
index 0fee66a3..66263fd1 100644
--- a/src/vorta/borg/create.py
+++ b/src/vorta/borg/create.py
@@ -66,7 +66,7 @@ def prepare(cls, profile):
& (WifiSettingModel.allowed == False)
& (WifiSettingModel.profile == profile.id)
)
- if wifi_is_disallowed.count() > 0:
+ if wifi_is_disallowed.count() > 0 and profile.repo.is_remote_repo():
ret['message'] = 'Current Wifi is not allowed.'
return ret
diff --git a/src/vorta/models.py b/src/vorta/models.py
index 27cefc07..f91b98e6 100644
--- a/src/vorta/models.py
+++ b/src/vorta/models.py
@@ -41,10 +41,21 @@ class RepoModel(pw.Model):
total_size = pw.IntegerField(null=True)
total_unique_chunks = pw.IntegerField(null=True)
+ def is_remote_repo(self):
+ return not self.url.startswith('/')
+
class Meta:
database = db
+class RepoPassword(pw.Model):
+ """Fallback to save repo passwords. Only used if no Keyring available."""
+ url = pw.CharField(unique=True)
+ password = pw.CharField()
+
+ class Meta:
+ database = db
+
class BackupProfileModel(pw.Model):
"""Allows the user to switch between different configurations."""
name = pw.CharField()
@@ -158,7 +169,7 @@ def _apply_schema_update(current_schema, version_after, *operations):
def init_db(con):
db.initialize(con)
db.connect()
- db.create_tables([RepoModel, BackupProfileModel, SourceDirModel,
+ db.create_tables([RepoModel, RepoPassword, BackupProfileModel, SourceDirModel,
SnapshotModel, WifiSettingModel, EventLogModel, SchemaVersion])
if BackupProfileModel.select().count() == 0:
diff --git a/src/vorta/utils.py b/src/vorta/utils.py
index 7a191d02..0464065f 100644
--- a/src/vorta/utils.py
+++ b/src/vorta/utils.py
@@ -9,18 +9,50 @@
from PyQt5.QtWidgets import QFileDialog
from PyQt5 import uic, QtCore
import subprocess
-
-"""Workaround for pyinstaller+keyring issue."""
import keyring
+from keyring import backend
+
+
+class VortaKeyring(backend.KeyringBackend):
+ """Fallback keyring service."""
+ @classmethod
+ def priority(cls):
+ return 5
+
+ def set_password(self, service, repo_url, password):
+ from .models import RepoPassword
+ keyring_entry, created = RepoPassword.get_or_create(url=repo_url, defaults={'password': password})
+ keyring_entry.password = password
+ keyring_entry.save()
+
+ def get_password(self, service, repo_url):
+ from .models import RepoPassword
+ try:
+ keyring_entry = RepoPassword.get(url=repo_url)
+ return keyring_entry.password
+ except Exception:
+ return None
+
+ def delete_password(self, service, repo_url):
+ pass
+
+
+"""Select keyring/Workaround for pyinstaller+keyring issue."""
if sys.platform == 'darwin':
from keyring.backends import OS_X
keyring.set_keyring(OS_X.Keyring())
elif sys.platform == 'win32':
from keyring.backends import Windows
keyring.set_keyring(Windows.WinVaultKeyring())
-else:
+elif sys.platform == 'linux':
from keyring.backends import SecretService
- keyring.set_keyring(SecretService.Keyring())
+ try:
+ SecretService.Keyring.priority() # Test if keyring works.
+ keyring.set_keyring(SecretService.Keyring())
+ except Exception:
+ keyring.set_keyring(VortaKeyring())
+else: # Fall back to saving password to database.
+ keyring.set_keyring(VortaKeyring())
from .models import WifiSettingModel
diff --git a/src/vorta/views/repo_tab.py b/src/vorta/views/repo_tab.py
index aa537c12..7fc477a0 100644
--- a/src/vorta/views/repo_tab.py
+++ b/src/vorta/views/repo_tab.py
@@ -158,9 +158,9 @@ def repo_unlink_action(self):
if selected_repo_index > 2:
repo = RepoModel.get(id=selected_repo_id)
SnapshotModel.delete().where(SnapshotModel.repo_id == repo.id).execute()
- repo.delete_instance()
profile.repo = None
profile.save()
+ repo.delete_instance(recursive=True) # This also deletes snapshots.
self.repoSelector.setCurrentIndex(0)
self.repoSelector.removeItem(selected_repo_index)
msg.setText('Repository was Unlinked')
diff --git a/src/vorta/views/schedule_tab.py b/src/vorta/views/schedule_tab.py
index a47ca94c..a1765c29 100644
--- a/src/vorta/views/schedule_tab.py
+++ b/src/vorta/views/schedule_tab.py
@@ -44,7 +44,7 @@ def populate_from_profile(self):
self.validationCheckBox.setTristate(False)
self.pruneCheckBox.setTristate(False)
- self._draw_next_scheduled_backup(profile.id)
+ self._draw_next_scheduled_backup()
self.init_wifi()
def init_wifi(self):
@@ -85,10 +85,10 @@ def init_logs(self):
self.logTableWidget.setItem(row, 3, QTableWidgetItem(log_line.repo_url))
self.logTableWidget.setItem(row, 4, QTableWidgetItem(str(log_line.returncode)))
self.logTableWidget.setRowCount(len(event_logs))
- self.nextBackupDateTimeLabel.setText(self.app.scheduler.next_job)
+ self._draw_next_scheduled_backup()
- def _draw_next_scheduled_backup(self, profile_id):
- self.nextBackupDateTimeLabel.setText(self.app.scheduler.next_job_for_profile(profile_id))
+ def _draw_next_scheduled_backup(self):
+ self.nextBackupDateTimeLabel.setText(self.app.scheduler.next_job_for_profile(self.profile().id))
self.nextBackupDateTimeLabel.repaint()
def on_scheduler_apply(self):
@@ -109,5 +109,5 @@ def on_scheduler_apply(self):
profile.schedule_fixed_hour, profile.schedule_fixed_minute = qtime.hour(), qtime.minute()
profile.save()
self.app.scheduler.reload()
- self._draw_next_scheduled_backup(profile.id)
+ self._draw_next_scheduled_backup()