When cleaning up after cron-job, remove expired queue items

- Implement KeyConfirmationQueue.delete_expired_queue_items to delete items
older than a given number of hours.

- Introduce configuration parameter to specify maximum number of hours.  It
defaults to 1 hour.

- Update documentation to explain that we never assign ST_TO_BE_DELETED.
This commit is contained in:
Piotr F. Mieszkowski 2024-04-05 17:19:01 +02:00
parent ce595971e1
commit e6619a660f
Signed by untrusted user: pfm
GPG key ID: BDE5BC1FA5DC53D5
4 changed files with 26 additions and 6 deletions

View file

@ -133,6 +133,10 @@ pooling_mode = optimistic
# made and closed after use, to avoid pool growth and connection rejections.
#max_overflow = 10
# Number of hours we will wait for the user to confirm their email. Cron-job
# will delete items older than this number of hours. Default: 1h.
#max_queue_hours = 1
[enc_keymap]
# You can find these by running the following command:
# gpg --list-keys --keyid-format long user@example.com

View file

@ -16,7 +16,8 @@ import sqlalchemy
# Values for lacre_keys.status column:
# - ST_DEFAULT: initial state;
# - ST_IMPORTED: key has been successfully processed by cron job;
# - ST_TO_BE_DELETED: key can be deleted.
# - ST_TO_BE_DELETED: key can be deleted. We only have checks for this value
# but never assign it, so this is a candidate for removal.
ST_DEFAULT, ST_IMPORTED, ST_TO_BE_DELETED = range(3)
# lacre_keys.confirmed is set to an empty string when a key is confirmed by the user.

View file

@ -1,5 +1,7 @@
"""Lacre identity and key repositories."""
from datetime import timedelta
from sqlalchemy import create_engine, select, delete, and_, func
from sqlalchemy.exc import OperationalError
import logging
@ -171,6 +173,16 @@ class KeyConfirmationQueue:
with self._engine.connect() as conn:
return [e for e in conn.execute(seldel)]
def delete_expired_queue_items(self, when):
max_hours = get_item('database', 'max_queue_hours', 1)
oldest = when - timedelta(hours=max_hours)
delq = delete(self._keys).where(self._keys.c.time < oldest)
LOG.debug('Deleting queue items older than %s: %s', repr(oldest), delq)
with self._engine.connect() as conn:
conn.execute(delq)
def delete_keys(self, row_id, /, email=None):
"""Remove key from the database."""
if email is not None:

View file

@ -20,6 +20,7 @@
#
import sys
from datetime import datetime
import logging
import lacre
import lacre.config as conf
@ -56,7 +57,7 @@ def import_key(key_dir, armored_key, key_id, email, key_queue, identities):
def import_failed(key_id, email, key_queue):
key_queue.delete_keys(key_id)
LOG.warning('Import confirmation failed: %s', email)
LOG.warning('Key confirmation failed: %s', email)
if conf.flag_enabled('cron', 'send_email'):
notify("PGP key registration failed", "registrationError.md", email)
@ -64,17 +65,16 @@ def import_failed(key_id, email, key_queue):
def delete_key(key_id, email, key_queue):
# delete key so we don't continue processing it
LOG.debug('Empty key received, just deleting')
LOG.debug('Empty key received, deleting known key from: %s', email)
key_queue.delete_keys(row_id)
key_queue.delete_keys(key_id, email)
if conf.flag_enabled('cron', 'send_email'):
notify("PGP key deleted", "keyDeleted.md", email)
def cleanup(key_dir, key_queue):
"""Delete keys and queue entries."""
LOG.info('Cleaning up after a round of key confirmation')
LOG.debug('Removing no longer needed keys from queue')
for email, row_id in key_queue.fetch_keys_to_delete():
LOG.debug('Removing key from keyring: %s', email)
GnuPG.delete_key(key_dir, email)
@ -84,6 +84,9 @@ def cleanup(key_dir, key_queue):
LOG.info('Deleted key for: %s', email)
now = datetime.now()
key_queue.delete_expired_queue_items(now)
_validate_config()