forked from Disroot/gpg-lacre
48 lines
1.5 KiB
Python
48 lines
1.5 KiB
Python
"""Database-backed keyring implementation."""
|
|
|
|
from lacre._keyringcommon import KeyRing, KeyCache
|
|
from lacre.dbschema import init_identities_table
|
|
import logging
|
|
import sqlalchemy
|
|
from sqlalchemy.sql import select
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class KeyRingSchema:
|
|
def __init__(self):
|
|
self._meta = sqlalchemy.MetaData()
|
|
self._id_table = init_identities_table()
|
|
|
|
def identities(self):
|
|
return self._id_table
|
|
|
|
|
|
class DatabaseKeyRing(KeyRing):
|
|
"""Database-backed key storage."""
|
|
|
|
def __init__(self, database_url, schema: KeyRingSchema):
|
|
self._schema = schema
|
|
self._url = database_url
|
|
self._initialised = False
|
|
|
|
def _ensure_initialised(self):
|
|
if not self._initialised:
|
|
self._engine = sqlalchemy.create_engine(self._url)
|
|
self._connection = self._engine.connect()
|
|
|
|
def load(self):
|
|
"""Do nothing, database contents doesn't need to be cached."""
|
|
pass
|
|
|
|
def freeze_identities(self) -> KeyCache:
|
|
"""Return a static, async-safe copy of the identity map."""
|
|
self._ensure_initialised()
|
|
return self._load_identities()
|
|
|
|
def _load_identities(self) -> KeyCache:
|
|
identities = self._schema.identities()
|
|
all_identities = select(identities.c.key_id, identities.c.email)
|
|
result = self._connection.execute(all_identities)
|
|
LOG.debug('Retrieving all keys')
|
|
return KeyCache({key_id: email for key_id, email in result})
|