Skip to content
Snippets Groups Projects
Commit cb89f598 authored by Philipp Hörist's avatar Philipp Hörist
Browse files

refactor: Remove side effects of password module

Fixes: #11032
parent dbf44701
No related branches found
No related tags found
No related merge requests found
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
from gajim.common import ged from gajim.common import ged
from gajim.common import configpaths from gajim.common import configpaths
from gajim.common import logging_helpers from gajim.common import logging_helpers
from gajim.common import passwords
from gajim.common.dbus import logind from gajim.common.dbus import logind
from gajim.common.events import AccountDisonnected from gajim.common.events import AccountDisonnected
from gajim.common.events import AllowGajimUpdateCheck from gajim.common.events import AllowGajimUpdateCheck
...@@ -61,6 +62,8 @@ def _init_core(self) -> None: ...@@ -61,6 +62,8 @@ def _init_core(self) -> None:
app.detect_dependencies() app.detect_dependencies()
configpaths.create_paths() configpaths.create_paths()
passwords.init()
app.settings = Settings() app.settings = Settings()
app.settings.init() app.settings.init()
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
from __future__ import annotations from __future__ import annotations
from typing import Optional from typing import Optional
from typing import cast
import logging import logging
...@@ -31,21 +32,34 @@ ...@@ -31,21 +32,34 @@
from gajim.common import app from gajim.common import app
__all__ = [ __all__ = [
'init',
'is_keyring_available',
'get_password', 'get_password',
'save_password', 'save_password',
'delete_password' 'delete_password'
] ]
log = logging.getLogger('gajim.password') log = logging.getLogger('gajim.c.passwords')
backends = keyring.backend.get_all_keyring()
for backend in backends:
log.info('Found keyring backend: %s', backend)
keyring_backend = keyring.get_keyring() class Interface:
log.info('Select %s backend', keyring_backend) def __init__(self):
self.backend = cast(keyring.backend.KeyringBackend, None)
self._is_keyring_available = False
KEYRING_AVAILABLE = keyring.core.recommended(keyring_backend) @property
def is_keyring_available(self):
return self._is_keyring_available
def init(self) -> None:
backends = keyring.backend.get_all_keyring()
for backend in backends:
log.info('Found keyring backend: %s', backend)
self.backend = keyring.get_keyring()
log.info('Select %s backend', self.backend)
self._is_keyring_available = keyring.core.recommended(self.backend)
class SecretPasswordStorage: class SecretPasswordStorage:
...@@ -55,13 +69,13 @@ class SecretPasswordStorage: ...@@ -55,13 +69,13 @@ class SecretPasswordStorage:
@staticmethod @staticmethod
def save_password(account_name: str, password: str) -> bool: def save_password(account_name: str, password: str) -> bool:
if not KEYRING_AVAILABLE: if not is_keyring_available():
log.warning('No recommended keyring backend available.' log.warning('No recommended keyring backend available.'
'Passwords cannot be stored.') 'Passwords cannot be stored.')
return True return True
try: try:
log.info('Save password to keyring') log.info('Save password to keyring')
keyring_backend.set_password('gajim', account_name, password) _interface.backend.set_password('gajim', account_name, password)
return True return True
except Exception: except Exception:
log.exception('Save password failed') log.exception('Save password failed')
...@@ -69,25 +83,28 @@ def save_password(account_name: str, password: str) -> bool: ...@@ -69,25 +83,28 @@ def save_password(account_name: str, password: str) -> bool:
@staticmethod @staticmethod
def get_password(account_name: str) -> Optional[str]: def get_password(account_name: str) -> Optional[str]:
log.info('Request password from keyring') if not is_keyring_available():
if not KEYRING_AVAILABLE:
return return
log.info('Request password from keyring')
try: try:
# For security reasons remove clear-text password # For security reasons remove clear-text password
ConfigPasswordStorage.delete_password(account_name) ConfigPasswordStorage.delete_password(account_name)
return keyring_backend.get_password('gajim', account_name) return _interface.backend.get_password('gajim', account_name)
except Exception: except Exception:
log.exception('Request password failed') log.exception('Request password failed')
return return
@staticmethod @staticmethod
def delete_password(account_name: str) -> None: def delete_password(account_name: str) -> None:
log.info('Remove password from keyring') if not is_keyring_available():
if not KEYRING_AVAILABLE:
return return
log.info('Remove password from keyring')
try: try:
return keyring_backend.delete_password('gajim', account_name) return _interface.backend.delete_password('gajim', account_name)
except keyring.errors.PasswordDeleteError as error: except keyring.errors.PasswordDeleteError as error:
log.warning('Removing password failed: %s', error) log.warning('Removing password failed: %s', error)
except Exception: except Exception:
...@@ -113,6 +130,14 @@ def delete_password(account_name: str) -> None: ...@@ -113,6 +130,14 @@ def delete_password(account_name: str) -> None:
app.settings.set_account_setting(account_name, 'password', '') app.settings.set_account_setting(account_name, 'password', '')
def init() -> None:
_interface.init()
def is_keyring_available() -> bool:
return _interface.is_keyring_available
def get_password(account_name: str) -> Optional[str]: def get_password(account_name: str) -> Optional[str]:
if app.settings.get('use_keyring'): if app.settings.get('use_keyring'):
return SecretPasswordStorage.get_password(account_name) return SecretPasswordStorage.get_password(account_name)
...@@ -138,3 +163,6 @@ def delete_password(account_name: str) -> None: ...@@ -138,3 +163,6 @@ def delete_password(account_name: str) -> None:
if app.settings.get('use_keyring'): if app.settings.get('use_keyring'):
return SecretPasswordStorage.delete_password(account_name) return SecretPasswordStorage.delete_password(account_name)
return ConfigPasswordStorage.delete_password(account_name) return ConfigPasswordStorage.delete_password(account_name)
_interface = Interface()
...@@ -1084,7 +1084,7 @@ def __init__(self, account: str, parent: Gtk.Window) -> None: ...@@ -1084,7 +1084,7 @@ def __init__(self, account: str, parent: Gtk.Window) -> None:
SettingType.ACCOUNT_CONFIG, SettingType.ACCOUNT_CONFIG,
'savepass', 'savepass',
enabled_func=(lambda: not app.settings.get('use_keyring') or enabled_func=(lambda: not app.settings.get('use_keyring') or
passwords.KEYRING_AVAILABLE)), passwords.is_keyring_available())),
Setting(SettingKind.CHANGEPASSWORD, Setting(SettingKind.CHANGEPASSWORD,
_('Change Password'), _('Change Password'),
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
from gi.repository import Gdk from gi.repository import Gdk
from gajim.common import app from gajim.common import app
from gajim.common import passwords
from gajim.common.i18n import _ from gajim.common.i18n import _
...@@ -125,7 +126,7 @@ def _get_features(self) -> list[Feature]: ...@@ -125,7 +126,7 @@ def _get_features(self) -> list[Feature]:
_('No additional requirements'), _('No additional requirements'),
notification_sounds_enabled), notification_sounds_enabled),
Feature(_('Secure Password Storage'), Feature(_('Secure Password Storage'),
self._some_keyring_available(), passwords.is_keyring_available(),
_('Enables Gajim to store Passwords securely instead of ' _('Enables Gajim to store Passwords securely instead of '
'storing them in plaintext'), 'storing them in plaintext'),
_('Requires: gnome-keyring or kwallet'), _('Requires: gnome-keyring or kwallet'),
...@@ -148,11 +149,6 @@ def _get_features(self) -> list[Feature]: ...@@ -148,11 +149,6 @@ def _get_features(self) -> list[Feature]:
None) None)
] ]
@staticmethod
def _some_keyring_available() -> bool:
from gajim.common import passwords
return passwords.KEYRING_AVAILABLE
@staticmethod @staticmethod
def _idle_available() -> bool: def _idle_available() -> bool:
from gajim.common import idle from gajim.common import idle
......
...@@ -18,10 +18,9 @@ ...@@ -18,10 +18,9 @@
from gi.repository import Gdk from gi.repository import Gdk
from gajim.common import app from gajim.common import app
from gajim.common import passwords
from gajim.common.events import PasswordRequired from gajim.common.events import PasswordRequired
from gajim.common.i18n import _ from gajim.common.i18n import _
from gajim.common.passwords import save_password
from gajim.common.passwords import KEYRING_AVAILABLE
from .builder import get_builder from .builder import get_builder
...@@ -69,9 +68,12 @@ def _process_event(self) -> None: ...@@ -69,9 +68,12 @@ def _process_event(self) -> None:
'jid': own_jid, 'jid': own_jid,
'account': account_name}) 'account': account_name})
self._ui.save_pass_checkbutton.show() self._ui.save_pass_checkbutton.show()
is_keyring_available = passwords.is_keyring_available()
self._ui.save_pass_checkbutton.set_sensitive( self._ui.save_pass_checkbutton.set_sensitive(
not app.settings.get('use_keyring') or KEYRING_AVAILABLE) not app.settings.get('use_keyring') or
if not KEYRING_AVAILABLE: is_keyring_available)
if not is_keyring_available:
self._ui.keyring_hint.show() self._ui.keyring_hint.show()
def _on_ok(self, _button: Gtk.Button) -> None: def _on_ok(self, _button: Gtk.Button) -> None:
...@@ -81,7 +83,7 @@ def _on_ok(self, _button: Gtk.Button) -> None: ...@@ -81,7 +83,7 @@ def _on_ok(self, _button: Gtk.Button) -> None:
self.account, self.account,
'savepass', 'savepass',
self._ui.save_pass_checkbutton.get_active()) self._ui.save_pass_checkbutton.get_active())
save_password(self.account, password) passwords.save_password(self.account, password)
self._event.on_password(password) self._event.on_password(password)
self.destroy() self.destroy()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment