mirror of
https://github.com/borgbase/vorta
synced 2025-01-03 13:45:49 +00:00
Add fallback keyring for systems without keyring backend. Fixes #10
This commit is contained in:
parent
99d8fa2d1e
commit
2d9e73bc3e
6 changed files with 56 additions and 13 deletions
|
@ -244,7 +244,7 @@
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="wordWrap">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -66,7 +66,7 @@ def prepare(cls, profile):
|
||||||
& (WifiSettingModel.allowed == False)
|
& (WifiSettingModel.allowed == False)
|
||||||
& (WifiSettingModel.profile == profile.id)
|
& (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.'
|
ret['message'] = 'Current Wifi is not allowed.'
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
|
@ -41,10 +41,21 @@ class RepoModel(pw.Model):
|
||||||
total_size = pw.IntegerField(null=True)
|
total_size = pw.IntegerField(null=True)
|
||||||
total_unique_chunks = pw.IntegerField(null=True)
|
total_unique_chunks = pw.IntegerField(null=True)
|
||||||
|
|
||||||
|
def is_remote_repo(self):
|
||||||
|
return not self.url.startswith('/')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
database = db
|
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):
|
class BackupProfileModel(pw.Model):
|
||||||
"""Allows the user to switch between different configurations."""
|
"""Allows the user to switch between different configurations."""
|
||||||
name = pw.CharField()
|
name = pw.CharField()
|
||||||
|
@ -158,7 +169,7 @@ def _apply_schema_update(current_schema, version_after, *operations):
|
||||||
def init_db(con):
|
def init_db(con):
|
||||||
db.initialize(con)
|
db.initialize(con)
|
||||||
db.connect()
|
db.connect()
|
||||||
db.create_tables([RepoModel, BackupProfileModel, SourceDirModel,
|
db.create_tables([RepoModel, RepoPassword, BackupProfileModel, SourceDirModel,
|
||||||
SnapshotModel, WifiSettingModel, EventLogModel, SchemaVersion])
|
SnapshotModel, WifiSettingModel, EventLogModel, SchemaVersion])
|
||||||
|
|
||||||
if BackupProfileModel.select().count() == 0:
|
if BackupProfileModel.select().count() == 0:
|
||||||
|
|
|
@ -9,18 +9,50 @@
|
||||||
from PyQt5.QtWidgets import QFileDialog
|
from PyQt5.QtWidgets import QFileDialog
|
||||||
from PyQt5 import uic, QtCore
|
from PyQt5 import uic, QtCore
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
"""Workaround for pyinstaller+keyring issue."""
|
|
||||||
import keyring
|
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':
|
if sys.platform == 'darwin':
|
||||||
from keyring.backends import OS_X
|
from keyring.backends import OS_X
|
||||||
keyring.set_keyring(OS_X.Keyring())
|
keyring.set_keyring(OS_X.Keyring())
|
||||||
elif sys.platform == 'win32':
|
elif sys.platform == 'win32':
|
||||||
from keyring.backends import Windows
|
from keyring.backends import Windows
|
||||||
keyring.set_keyring(Windows.WinVaultKeyring())
|
keyring.set_keyring(Windows.WinVaultKeyring())
|
||||||
else:
|
elif sys.platform == 'linux':
|
||||||
from keyring.backends import SecretService
|
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
|
from .models import WifiSettingModel
|
||||||
|
|
|
@ -158,9 +158,9 @@ def repo_unlink_action(self):
|
||||||
if selected_repo_index > 2:
|
if selected_repo_index > 2:
|
||||||
repo = RepoModel.get(id=selected_repo_id)
|
repo = RepoModel.get(id=selected_repo_id)
|
||||||
SnapshotModel.delete().where(SnapshotModel.repo_id == repo.id).execute()
|
SnapshotModel.delete().where(SnapshotModel.repo_id == repo.id).execute()
|
||||||
repo.delete_instance()
|
|
||||||
profile.repo = None
|
profile.repo = None
|
||||||
profile.save()
|
profile.save()
|
||||||
|
repo.delete_instance(recursive=True) # This also deletes snapshots.
|
||||||
self.repoSelector.setCurrentIndex(0)
|
self.repoSelector.setCurrentIndex(0)
|
||||||
self.repoSelector.removeItem(selected_repo_index)
|
self.repoSelector.removeItem(selected_repo_index)
|
||||||
msg.setText('Repository was Unlinked')
|
msg.setText('Repository was Unlinked')
|
||||||
|
|
|
@ -44,7 +44,7 @@ def populate_from_profile(self):
|
||||||
self.validationCheckBox.setTristate(False)
|
self.validationCheckBox.setTristate(False)
|
||||||
self.pruneCheckBox.setTristate(False)
|
self.pruneCheckBox.setTristate(False)
|
||||||
|
|
||||||
self._draw_next_scheduled_backup(profile.id)
|
self._draw_next_scheduled_backup()
|
||||||
self.init_wifi()
|
self.init_wifi()
|
||||||
|
|
||||||
def init_wifi(self):
|
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, 3, QTableWidgetItem(log_line.repo_url))
|
||||||
self.logTableWidget.setItem(row, 4, QTableWidgetItem(str(log_line.returncode)))
|
self.logTableWidget.setItem(row, 4, QTableWidgetItem(str(log_line.returncode)))
|
||||||
self.logTableWidget.setRowCount(len(event_logs))
|
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):
|
def _draw_next_scheduled_backup(self):
|
||||||
self.nextBackupDateTimeLabel.setText(self.app.scheduler.next_job_for_profile(profile_id))
|
self.nextBackupDateTimeLabel.setText(self.app.scheduler.next_job_for_profile(self.profile().id))
|
||||||
self.nextBackupDateTimeLabel.repaint()
|
self.nextBackupDateTimeLabel.repaint()
|
||||||
|
|
||||||
def on_scheduler_apply(self):
|
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.schedule_fixed_hour, profile.schedule_fixed_minute = qtime.hour(), qtime.minute()
|
||||||
profile.save()
|
profile.save()
|
||||||
self.app.scheduler.reload()
|
self.app.scheduler.reload()
|
||||||
self._draw_next_scheduled_backup(profile.id)
|
self._draw_next_scheduled_backup()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue