This repository has been archived on 2023-02-02. You can view files and clone it, but cannot push or open issues or pull requests.
barkshark-web/barkshark_web/passwords/base.py

258 lines
4.5 KiB
Python

from izzylib.misc import class_name
from . import PASSWORD_STORAGE
from ..functions import TimeoutCallback, get_app, run_in_gui_thread
PASSWORD_KEYS = [
'id',
'label',
'username',
'password',
'domain',
'url',
'note',
'created',
'modified'
]
class PasswordResult:
def __init__(self, storage, items):
self._storage = storage
self._items = items
def __iter__(self):
for item in self._items:
yield self._storage.item_class(self._storage, item)
def all(self):
return tuple(item for item in self)
def one(self):
for item in self:
return item
class PasswordItem:
def __init__(self, storage, item):
self._storage = storage
self._data = item
def __repr__(self):
return f'{class_name(self)}("{self.label}", username="{self.username}", domain="{self.domain}")'
def __getitem__(self, key):
if key not in self.keys():
raise KeyError(key)
value = self._get_value(key)
return self.__default_parse(key, value)
def __setitem__(self, key, value):
if key in ['id', 'created', 'modified'] or key not in self.keys():
raise KeyError(key)
value = self.__default_parse(key, value)
self._set_value(key, value)
def __delitem__(self, key):
raise AttributeError('Cannot delete item values')
def __getattr__(self, key):
try:
return self.__getitem__(key)
except KeyError:
return object.__getattribute__(self, key)
def __setattr__(self, key, value):
try:
self.__setitem__(key, value)
except KeyError:
object.__setattr__(self, key, value)
def __default_parse(self, key, value):
if key == 'url' and not isinstance(value, (Url, type(None))):
return Url(value)
elif key in ['created', 'modified'] and not isinstance(value, (DateString, type(None))):
return DateString.new_http(value)
return self._parse_value(key, value)
def _parse_value(self, key, value):
return value
def _get_value(self, key):
return self._item[key]
def _set_value(self, key, value):
self._item[key] = value
def copy_password(self, timeout=60):
app = get_app()
app.set_clipboard_text(self.password)
timer = TimeoutCallback(timeout, run_in_gui_thread, app.handle_clipboard_clear_password, self.password)
timer.start()
def copy_username(self):
get_app().set_clipboard_text(self.username)
def insert_row(self, storage=None):
if self.id:
raise RuntimeError('Row already has an ID and is probably in the DB')
if storage:
return storage.insert(**self.to_dict())
return self._storage.insert(**self.to_dict())
def update_row(self, **kwargs):
self.update(**kwargs)
self._storage.update(self.id, **kwargs)
def remove_row(self):
self._storage.remove(self.id)
def to_dict(self, indent=None):
return DotDict({key: self[key] for key in self.keys()})
## dict methods
def items(self):
for key in self.keys():
yield (key, self[key])
def keys(self):
return PASSWORD_KEYS.copy()
def values(self):
return tuple(self[key] for key in self.keys())
def update(self, _data={}, **kwargs):
for key, value in [*_data.items(), *kwargs.items()]:
if key not in self.keys():
raise KeyError(f'Invalid PasswordItem key: {key}')
self[key] = value
class PasswordStorage:
result_class = PasswordResult
item_class = PasswordItem
@property
def app(self):
return get_app()
@property
def window(self):
return self.app.window
@property
def storage_type(self):
for key, value in PASSWORD_STORAGE.items():
if self.__class__ == value:
return key
def start(self):
pass
def stop(self):
pass
def _fetch(self, **kwargs):
pass
def lock(self):
pass
def unlock(self, password=None):
pass
def create_row(self, *args, **kwargs):
return self.item_class.new(*args, **kwargs, storage=self)
def parse_data(self, username=None, domain=None, password=None, url=None, note=None, label=None, **kwargs):
kwargs.update(
username = username,
domain = domain,
url = url,
note = note,
password = password,
label = label
)
for key, value in tuple(kwargs.items()):
if not value:
del kwargs[key]
elif key == 'url':
kwargs['url'] = Url(url)
return kwargs
def fetch(self, label=None, username=None, domain=None, **kwargs):
if not any((name, username, domain)):
raise ValueError('Name, username, or domain not provided')
if name:
kwargs['name'] = name
if username:
kwargs['username'] = username
if domain:
kwargs['domain'] = domain
return self.result_class(self, self._fetch(**kwargs))
def insert(self, name, username, domain, **kwargs):
pass
def update(self, row_id, **kwargs):
pass
def remove(self, row_id):
pass