Clean up database access

- Don't pass table definitions to repository constructors.

- Keep an internal reference to Engine in lacre.repository.

- Implement KeyConfirmationQueue.count_keys.
This commit is contained in:
Piotr F. Mieszkowski 2023-11-25 14:04:32 +01:00
parent 4950e0b9c3
commit becb39f139
4 changed files with 32 additions and 22 deletions

View File

@ -16,7 +16,7 @@ LOG = logging.getLogger(__name__)
def init_keyring() -> KeyRing:
"""Initialise appropriate type of keyring."""
url = conf.get_item('database', 'url')
return IdentityRepository(GPGMW_IDENTITIES, db_url=url)
return IdentityRepository(db_url=url)
def freeze_and_load_keys() -> KeyCache:

View File

@ -1,6 +1,6 @@
"""Lacre identity and key repositories."""
from sqlalchemy import create_engine, select, delete, and_
from sqlalchemy import create_engine, select, delete, and_, func
import logging
from lacre._keyringcommon import KeyRing, KeyCache
@ -9,9 +9,20 @@ import lacre.dbschema as db
LOG = logging.getLogger(__name__)
# Internal state
_engine = None
def connect(url):
global _engine
if not _engine:
_engine = create_engine(url)
return _engine.connect()
class IdentityRepository(KeyRing):
def __init__(self, identity_table, connection=None, db_url=None):
self._identities = identity_table
def __init__(self, /, connection=None, db_url=None):
self._identities = db.GPGMW_IDENTITIES
self._conn = connection
self._url = db_url
self._initialised = connection is not None
@ -78,8 +89,8 @@ class KeyConfirmationQueue:
# Default number of items retrieved from the database.
keys_read_max = 100
def __init__(self, keys_table, connection):
self._keys = keys_table
def __init__(self, connection):
self._keys = db.GPGMW_KEYS
self._conn = connection
def fetch_keys(self, /, max_keys=None):
@ -93,6 +104,15 @@ class KeyConfirmationQueue:
LOG.debug('Retrieving keys to be processed: %s', selq)
return self._conn.execute(selq)
def count_keys(self):
selq = select(func.count(self._keys.c.id))
LOG.debug('Counting all keys: %s', selq)
c = [cnt for cnt in self._conn.execute(selq)]
# Result is an iterable of tuples:
return c[0][0]
def fetch_keys_to_delete(self):
seldel = select(self._keys.c.email, self._keys.c.id).where(self._keys.c.status == db.ST_TO_BE_DELETED).limit(self.keys_read_max)
return self._conn.execute(seldel)

View File

@ -8,7 +8,7 @@ import lacre.dbschema as s
class IdentityRepositoryTest(unittest.TestCase):
def test_x(self):
ir = r.IdentityRepository(s.GPGMW_IDENTITIES, db_url='sqlite:///test/lacre.db')
ir = r.IdentityRepository(db_url='sqlite:///test/lacre.db')
identities = ir.freeze_identities()
self.assertTrue(identities)

View File

@ -38,33 +38,23 @@ lacre.init_logging(conf.get_item('logging', 'config'))
LOG = logging.getLogger('webgate-cron.py')
import GnuPG
from lacre.repositories import KeyConfirmationQueue, IdentityRepository
def _setup_db_connection(url):
engine = sqlalchemy.create_engine(url)
LOG.debug('Initialised database engine: %s', engine)
return (engine, engine.connect())
def _define_db_schema():
return (db.GPGMW_KEYS, db.GPGMW_IDENTITIES)
from lacre.repositories import KeyConfirmationQueue, IdentityRepository, connect
def _validate_config():
missing = conf.validate_config(additional=conf.CRON_REQUIRED)
if missing:
LOG.error('Missing config parameters: %s', missing)
exit(lacre.EX_CONFIG)
_validate_config()
if conf.flag_enabled('database', 'enabled') and conf.config_item_set('database', 'url'):
(engine, conn) = _setup_db_connection(conf.get_item("database", "url"))
(gpgmw_keys, gpgmw_identities) = _define_db_schema()
conn = connect(conf.get_item('database', 'url'))
identities = IdentityRepository(gpgmw_identities, conn)
key_queue = KeyConfirmationQueue(gpgmw_keys, conn)
identities = IdentityRepository(conn)
key_queue = KeyConfirmationQueue(conn)
key_dir = conf.get_item('gpg', 'keyhome')
LOG.debug('Using GnuPG with home directory in %s', key_dir)