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/sql.py

183 lines
3.8 KiB
Python

from datetime import datetime
from .base import PasswordItem, PasswordStorage
class SqlItem(PasswordItem):
def __init__(self, storage, row):
self._storage = storage
self._data = row
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', 'domain'] 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.row[key]
def _set_value(self, key, value):
self.row[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):
kwargs.update(data)
self.data.update(kwargs)
class SqlStorage(PasswordStorage):
item_class = SqlItem
def __init__(self, db):
self.db = db
def fetch(self, *args, deleted=None, **kwargs):
with self.db.session as s:
if (rowid := kwargs.get('id')):
if not (row := s.fetch('passwords', id=rowid).one()):
raise NoPasswordError(rowid)
return row
data = self.parse_data(*args, **kwargs)
return s.fetch('passwords', **data)
def insert(self, *args, **kwargs):
data = self.parse_data(*args, **kwargs)
data['created'] = datetime.now()
if not data.get('domain') and data.get('url'):
data['domain'] = data['url'].hostname()
with self.db.session as s:
s.insert('passwords', **data)
return s.fetch('passwords',
username = data['username'],
password = data['password'],
domain = data['url'].domain if data.get('url') else None
).one()
def update(self, row_id, *args, **kwargs):
data = self.parse_data(*args, **kwargs)
data['modified'] = datetime.now()
if (url := data.get('domain')):
data['domain'] = url.hostname()
with self.db.session as s:
s.update('passwords', data, id=row_id)
return s.fetch('passwords', id=row_id).one()
def remove(self, row_id):
with self.db.session as s:
s.remove('passwords', id=row_id)
return True