Print schleuder names in conflict messages, rather than ids

This commit is contained in:
s3lph 2022-04-18 22:00:19 +02:00
parent 4b9dfa550a
commit d122e9033e
7 changed files with 63 additions and 34 deletions

View file

@ -17,7 +17,7 @@ from datetime import datetime
import pgpy # type: ignore import pgpy # type: ignore
from multischleuder.reporting import KeyConflictMessage, Message, UserConflictMessage from multischleuder.reporting import KeyConflictMessage, Message, UserConflictMessage
from multischleuder.types import SchleuderKey, SchleuderSubscriber from multischleuder.types import SchleuderKey, SchleuderList, SchleuderSubscriber
class KeyConflictResolution: class KeyConflictResolution:
@ -36,7 +36,9 @@ class KeyConflictResolution:
def resolve(self, def resolve(self,
target: str, target: str,
mail_from: str, mail_from: str,
subscriptions: List[SchleuderSubscriber]) -> Tuple[List[SchleuderSubscriber], List[Optional[Message]]]: subscriptions: List[SchleuderSubscriber],
sources: List[SchleuderList]) -> Tuple[List[SchleuderSubscriber], List[Optional[Message]]]:
sourcemap: Dict[int, str] = {s.id: s.name for s in sources}
conflicts: List[Optional[Message]] = [] conflicts: List[Optional[Message]] = []
# First check for keys that are being used by more than one subscriber # First check for keys that are being used by more than one subscriber
@ -47,7 +49,7 @@ class KeyConflictResolution:
keys.setdefault(s.key.fingerprint, []).append(s) keys.setdefault(s.key.fingerprint, []).append(s)
key_resolved: List[SchleuderSubscriber] = [] key_resolved: List[SchleuderSubscriber] = []
for k in keys.values(): for k in keys.values():
rk, m = self._resolve_users(target, mail_from, k) rk, m = self._resolve_users(target, mail_from, k, sourcemap)
if rk is not None: if rk is not None:
key_resolved.append(rk) key_resolved.append(rk)
if m is not None: if m is not None:
@ -60,7 +62,7 @@ class KeyConflictResolution:
# Perform conflict resolution for each set of subscribers with the same email # Perform conflict resolution for each set of subscribers with the same email
resolved: List[SchleuderSubscriber] = [] resolved: List[SchleuderSubscriber] = []
for c in subs.values(): for c in subs.values():
r, msg = self._resolve_keys(target, mail_from, c) r, msg = self._resolve_keys(target, mail_from, c, sourcemap)
if r is not None: if r is not None:
resolved.append(r) resolved.append(r)
if msg is not None: if msg is not None:
@ -70,7 +72,8 @@ class KeyConflictResolution:
def _resolve_keys(self, def _resolve_keys(self,
target: str, target: str,
mail_from: str, mail_from: str,
subscriptions: List[SchleuderSubscriber]) \ subscriptions: List[SchleuderSubscriber],
sourcemap: Dict[int, str]) \
-> Tuple[Optional[SchleuderSubscriber], Optional[Message]]: -> Tuple[Optional[SchleuderSubscriber], Optional[Message]]:
notnull = [s for s in subscriptions if s.key is not None] notnull = [s for s in subscriptions if s.key is not None]
if len(notnull) == 0: if len(notnull) == 0:
@ -96,7 +99,8 @@ class KeyConflictResolution:
subscriptions, subscriptions,
digest, digest,
mail_from, mail_from,
self._key_template self._key_template,
sourcemap
) )
# Return the result of conflict resolution # Return the result of conflict resolution
return earliest, msg return earliest, msg
@ -104,7 +108,8 @@ class KeyConflictResolution:
def _resolve_users(self, def _resolve_users(self,
target: str, target: str,
mail_from: str, mail_from: str,
subscriptions: List[SchleuderSubscriber]) \ subscriptions: List[SchleuderSubscriber],
sourcemap: Dict[int, str]) \
-> Tuple[Optional[SchleuderSubscriber], Optional[List[Message]]]: -> Tuple[Optional[SchleuderSubscriber], Optional[List[Message]]]:
notnull = [s for s in subscriptions if s.key is not None] notnull = [s for s in subscriptions if s.key is not None]
if len(notnull) == 0: if len(notnull) == 0:
@ -133,7 +138,8 @@ class KeyConflictResolution:
subscriptions, subscriptions,
digest, digest,
mail_from, mail_from,
self._user_template self._user_template,
sourcemap
)) ))
# Return the result of conflict resolution # Return the result of conflict resolution
return earliest, msgs return earliest, msgs

View file

@ -50,7 +50,7 @@ class MultiList:
continue continue
all_subs.append(s) all_subs.append(s)
# ... which is taken care of by the key conflict resolution routine # ... which is taken care of by the key conflict resolution routine
resolved, conflicts = self._kcr.resolve(self._target, self._mail_from, all_subs) resolved, conflicts = self._kcr.resolve(self._target, self._mail_from, all_subs, sources)
self._reporter.add_messages(conflicts) self._reporter.add_messages(conflicts)
intended_subs: Set[SchleuderSubscriber] = set(resolved) intended_subs: Set[SchleuderSubscriber] = set(resolved)
intended_keys: Set[SchleuderKey] = {s.key for s in intended_subs if s.key is not None} intended_keys: Set[SchleuderKey] = {s.key for s in intended_subs if s.key is not None}

View file

@ -91,14 +91,16 @@ class KeyConflictMessage(Message):
affected: List[SchleuderSubscriber], affected: List[SchleuderSubscriber],
digest: str, digest: str,
mail_from: str, mail_from: str,
template: str): template: str,
sourcemap: Dict[int, str]):
# Render the message body # Render the message body
fpr = 'no key' if chosen.key is None else chosen.key.fingerprint fpr = 'no key' if chosen.key is None else chosen.key.fingerprint
_chosen = f'{fpr} {chosen.email}' _chosen = f'{fpr} {chosen.email}'
_affected = '' _affected = ''
for a in affected: for a in affected:
fpr = 'no key' if a.key is None else a.key.fingerprint fpr = 'no key' if a.key is None else a.key.fingerprint
_affected += f'{fpr} {a.schleuder}\n' aschleuder: str = sourcemap.get(a.schleuder, 'unknown')
_affected += f'{fpr} {aschleuder}\n'
content = template.format( content = template.format(
subscriber=chosen.email, subscriber=chosen.email,
schleuder=schleuder, schleuder=schleuder,
@ -128,13 +130,15 @@ class UserConflictMessage(Message):
affected: List[SchleuderSubscriber], affected: List[SchleuderSubscriber],
digest: str, digest: str,
mail_from: str, mail_from: str,
template: str): template: str,
sourcemap: Dict[int, str]):
# Render the message body # Render the message body
assert chosen.key is not None assert chosen.key is not None
_chosen = chosen.email _chosen = chosen.email
_affected = '' _affected = ''
for a in affected: for a in affected:
_affected += f'{a.email} {a.schleuder}\n' aschleuder: str = sourcemap.get(a.schleuder, 'unknown')
_affected += f'{a.email} {aschleuder}\n'
content = template.format( content = template.format(
subscriber=subscriber, subscriber=subscriber,
fingerprint=chosen.key.fingerprint, fingerprint=chosen.key.fingerprint,

View file

@ -123,7 +123,7 @@ class TestKeyConflictResolution(unittest.TestCase):
contents.seek(io.SEEK_END) # Opened with 'a+' contents.seek(io.SEEK_END) # Opened with 'a+'
with patch('builtins.open', mock_open(read_data=_CONFLICT_STATE_NONE)) as mock_statefile: with patch('builtins.open', mock_open(read_data=_CONFLICT_STATE_NONE)) as mock_statefile:
mock_statefile().__enter__.return_value = contents mock_statefile().__enter__.return_value = contents
resolved, messages = kcr.resolve('', '', []) resolved, messages = kcr.resolve('', '', [], [])
self.assertEqual(0, len(resolved)) self.assertEqual(0, len(resolved))
self.assertEqual(0, len(messages)) self.assertEqual(0, len(messages))
@ -133,7 +133,7 @@ class TestKeyConflictResolution(unittest.TestCase):
date1 = datetime(2022, 4, 15, 5, 23, 42, 0, tzinfo=tzutc()) date1 = datetime(2022, 4, 15, 5, 23, 42, 0, tzinfo=tzutc())
sub1 = SchleuderSubscriber(3, 'foo@example.org', key1, sch1.id, date1) sub1 = SchleuderSubscriber(3, 'foo@example.org', key1, sch1.id, date1)
kcr = KeyConflictResolution(3600, '/tmp/state.json', _KEY_TEMPLATE, _USER_TEMPLATE) kcr = KeyConflictResolution(3600, '/tmp/state.json', _KEY_TEMPLATE, _USER_TEMPLATE)
resolved, messages = kcr.resolve('', '', [sub1]) resolved, messages = kcr.resolve('', '', [sub1], [sch1])
self.assertEqual(1, len(resolved)) self.assertEqual(1, len(resolved))
self.assertEqual(sub1, resolved[0]) self.assertEqual(sub1, resolved[0])
self.assertEqual(0, len(messages)) self.assertEqual(0, len(messages))
@ -158,7 +158,8 @@ class TestKeyConflictResolution(unittest.TestCase):
resolved, messages = kcr.resolve( resolved, messages = kcr.resolve(
target='test@schleuder.example.org', target='test@schleuder.example.org',
mail_from='test-owner@schleuder.example.org', mail_from='test-owner@schleuder.example.org',
subscriptions=[sub1, sub2]) subscriptions=[sub1, sub2],
sources=[sch1, sch2])
self.assertEqual(1, len(resolved)) self.assertEqual(1, len(resolved))
self.assertEqual('2FBBC0DF97FDBF1E4B704EEDE39EF4FAC420BEB6', resolved[0].key.fingerprint) self.assertEqual('2FBBC0DF97FDBF1E4B704EEDE39EF4FAC420BEB6', resolved[0].key.fingerprint)
@ -185,7 +186,8 @@ class TestKeyConflictResolution(unittest.TestCase):
resolved, messages = kcr.resolve( resolved, messages = kcr.resolve(
target='test@schleuder.example.org', target='test@schleuder.example.org',
mail_from='test-owner@schleuder.example.org', mail_from='test-owner@schleuder.example.org',
subscriptions=[sub1, sub2]) subscriptions=[sub1, sub2],
sources=[sch1, sch2])
self.assertEqual(1, len(resolved)) self.assertEqual(1, len(resolved))
self.assertEqual('135AFA0FB3FF584828911208B7913308392972A4', resolved[0].key.fingerprint) self.assertEqual('135AFA0FB3FF584828911208B7913308392972A4', resolved[0].key.fingerprint)
@ -222,7 +224,8 @@ class TestKeyConflictResolution(unittest.TestCase):
resolved, messages = kcr.resolve( resolved, messages = kcr.resolve(
target='test@schleuder.example.org', target='test@schleuder.example.org',
mail_from='test-owner@schleuder.example.org', mail_from='test-owner@schleuder.example.org',
subscriptions=[sub1, sub2]) subscriptions=[sub1, sub2],
sources=[sch1, sch2])
self.assertEqual(1, len(resolved)) self.assertEqual(1, len(resolved))
self.assertEqual('2FBBC0DF97FDBF1E4B704EEDE39EF4FAC420BEB6', resolved[0].key.fingerprint) self.assertEqual('2FBBC0DF97FDBF1E4B704EEDE39EF4FAC420BEB6', resolved[0].key.fingerprint)
@ -242,7 +245,8 @@ class TestKeyConflictResolution(unittest.TestCase):
resolved, messages = kcr.resolve( resolved, messages = kcr.resolve(
target='test@schleuder.example.org', target='test@schleuder.example.org',
mail_from='test-owner@schleuder.example.org', mail_from='test-owner@schleuder.example.org',
subscriptions=[sub1]) subscriptions=[sub1],
sources=[sch1])
self.assertEqual(0, len(resolved)) self.assertEqual(0, len(resolved))
self.assertEqual(0, len(messages)) self.assertEqual(0, len(messages))
@ -266,7 +270,8 @@ class TestKeyConflictResolution(unittest.TestCase):
resolved, messages = kcr.resolve( resolved, messages = kcr.resolve(
target='test@schleuder.example.org', target='test@schleuder.example.org',
mail_from='test-owner@schleuder.example.org', mail_from='test-owner@schleuder.example.org',
subscriptions=[sub1, sub2]) subscriptions=[sub1, sub2],
sources=[sch1, sch2])
self.assertEqual(1, len(resolved)) self.assertEqual(1, len(resolved))
self.assertEqual('bar@example.org', resolved[0].email) self.assertEqual('bar@example.org', resolved[0].email)
@ -318,7 +323,8 @@ class TestKeyConflictResolution(unittest.TestCase):
resolved, messages = kcr.resolve( resolved, messages = kcr.resolve(
target='test@schleuder.example.org', target='test@schleuder.example.org',
mail_from='test-owner@schleuder.example.org', mail_from='test-owner@schleuder.example.org',
subscriptions=[sub1, sub2, sub3]) subscriptions=[sub1, sub2, sub3],
sources=[sch1, sch2])
self.assertEqual(2, len(resolved)) self.assertEqual(2, len(resolved))
foo, bar = resolved foo, bar = resolved
@ -369,7 +375,8 @@ class TestKeyConflictResolution(unittest.TestCase):
resolved, msgs = kcr.resolve( resolved, msgs = kcr.resolve(
target='test@schleuder.example.org', target='test@schleuder.example.org',
mail_from='test-owner@schleuder.example.org', mail_from='test-owner@schleuder.example.org',
subscriptions=[sub1, sub2]) subscriptions=[sub1, sub2],
sources=[sch1, sch2])
self.assertEqual(0, len(msgs)) self.assertEqual(0, len(msgs))
def test_send_messages_brokenstate(self): def test_send_messages_brokenstate(self):
@ -391,7 +398,8 @@ class TestKeyConflictResolution(unittest.TestCase):
resolved, msgs = kcr.resolve( resolved, msgs = kcr.resolve(
target='test@schleuder.example.org', target='test@schleuder.example.org',
mail_from='test-owner@schleuder.example.org', mail_from='test-owner@schleuder.example.org',
subscriptions=[sub1, sub2]) subscriptions=[sub1, sub2],
sources=[sch1, sch2])
self.assertEqual(0, len(msgs)) self.assertEqual(0, len(msgs))
def test_send_messages_emptystate(self): def test_send_messages_emptystate(self):
@ -412,7 +420,8 @@ class TestKeyConflictResolution(unittest.TestCase):
resolved, msgs = kcr.resolve( resolved, msgs = kcr.resolve(
target='test@schleuder.example.org', target='test@schleuder.example.org',
mail_from='test-owner@schleuder.example.org', mail_from='test-owner@schleuder.example.org',
subscriptions=[sub1, sub2]) subscriptions=[sub1, sub2],
sources=[sch1, sch2])
self.assertEqual(1, len(msgs)) self.assertEqual(1, len(msgs))
now = datetime.utcnow().timestamp() now = datetime.utcnow().timestamp()
@ -442,7 +451,8 @@ class TestKeyConflictResolution(unittest.TestCase):
resolved, msgs = kcr.resolve( resolved, msgs = kcr.resolve(
target='test@schleuder.example.org', target='test@schleuder.example.org',
mail_from='test-owner@schleuder.example.org', mail_from='test-owner@schleuder.example.org',
subscriptions=[sub1, sub2]) subscriptions=[sub1, sub2],
sources=[sch1, sch2])
self.assertEqual(1, len(msgs)) self.assertEqual(1, len(msgs))
now = datetime.utcnow().timestamp() now = datetime.utcnow().timestamp()
@ -472,7 +482,8 @@ class TestKeyConflictResolution(unittest.TestCase):
resolved, messages = kcr.resolve( resolved, messages = kcr.resolve(
target='test@schleuder.example.org', target='test@schleuder.example.org',
mail_from='test-owner@schleuder.example.org', mail_from='test-owner@schleuder.example.org',
subscriptions=[sub1, sub2]) subscriptions=[sub1, sub2],
sources=[sch1, sch2])
self.assertEqual(1, len(messages)) self.assertEqual(1, len(messages))
msg = messages[0] msg = messages[0]
@ -503,7 +514,8 @@ class TestKeyConflictResolution(unittest.TestCase):
resolved, messages = kcr.resolve( resolved, messages = kcr.resolve(
target='test@schleuder.example.org', target='test@schleuder.example.org',
mail_from='test-owner@schleuder.example.org', mail_from='test-owner@schleuder.example.org',
subscriptions=[sub1, sub2]) subscriptions=[sub1, sub2],
sources=[sch1, sch2])
self.assertEqual(0, len(messages)) self.assertEqual(0, len(messages))
now = datetime.utcnow().timestamp() now = datetime.utcnow().timestamp()
@ -536,7 +548,8 @@ class TestKeyConflictResolution(unittest.TestCase):
resolved, messages = kcr.resolve( resolved, messages = kcr.resolve(
target='test@schleuder.example.org', target='test@schleuder.example.org',
mail_from='test-owner@schleuder.example.org', mail_from='test-owner@schleuder.example.org',
subscriptions=[sub1, sub2]) subscriptions=[sub1, sub2],
sources=[sch1, sch2])
self.assertEqual(1, len(messages)) self.assertEqual(1, len(messages))
now = datetime.utcnow().timestamp() now = datetime.utcnow().timestamp()
@ -568,7 +581,8 @@ class TestKeyConflictResolution(unittest.TestCase):
resolved, messages = kcr.resolve( resolved, messages = kcr.resolve(
target='test@schleuder.example.org', target='test@schleuder.example.org',
mail_from='test-owner@schleuder.example.org', mail_from='test-owner@schleuder.example.org',
subscriptions=[sub1, sub2, sub3]) subscriptions=[sub1, sub2, sub3],
sources=[sch1, sch2, sch3])
self.assertEqual(1, len(messages)) self.assertEqual(1, len(messages))
msg = messages[0].mime msg = messages[0].mime
pgp = pgpy.PGPMessage.from_blob(msg.get_payload()[1].get_payload(decode=True)) pgp = pgpy.PGPMessage.from_blob(msg.get_payload()[1].get_payload(decode=True))

View file

@ -14,7 +14,8 @@ from multischleuder.types import SchleuderKey, SchleuderList, SchleuderSubscribe
def _resolve(target: str, def _resolve(target: str,
mail_from: str, mail_from: str,
subscriptions: List[SchleuderSubscriber]) -> Tuple[List[SchleuderSubscriber], List[Message]]: subscriptions: List[SchleuderSubscriber],
sources: List[SchleuderList]) -> Tuple[List[SchleuderSubscriber], List[Message]]:
# Mock conflict resolution that does not send or prepare messages # Mock conflict resolution that does not send or prepare messages
subs: Dict[str, List[SchleuderSubscriber]] = {} subs: Dict[str, List[SchleuderSubscriber]] = {}
for s in subscriptions: for s in subscriptions:

View file

@ -18,7 +18,8 @@ def one_of_each_kind():
affected=[sub], affected=[sub],
digest='digest', digest='digest',
mail_from='test-owner@example.org', mail_from='test-owner@example.org',
template='averylongmessage') template='averylongmessage',
sourcemap={1: 'test@example.org'})
msg2 = AdminReport( msg2 = AdminReport(
schleuder='test@example.org', schleuder='test@example.org',
mail_to='admin@example.org', mail_to='admin@example.org',
@ -36,7 +37,8 @@ def one_of_each_kind():
affected=[sub2], affected=[sub2],
digest='digest', digest='digest',
mail_from='test-owner@example.org', mail_from='test-owner@example.org',
template='averylongmessage') template='averylongmessage',
sourcemap={1: 'test@example.org'})
return [msg1, msg2, msg3] return [msg1, msg2, msg3]

View file

@ -176,7 +176,8 @@ class TestSmtpClient(unittest.TestCase):
affected=[sub], affected=[sub],
digest='digest', digest='digest',
mail_from='test-owner@example.org', mail_from='test-owner@example.org',
template='averylongmessage') template='averylongmessage',
sourcemap={1: 'foo@example.org'})
msg2 = AdminReport( msg2 = AdminReport(
schleuder='test@example.org', schleuder='test@example.org',
mail_to='admin@example.org', mail_to='admin@example.org',
@ -209,7 +210,8 @@ class TestSmtpClient(unittest.TestCase):
affected=[sub], affected=[sub],
digest='digest', digest='digest',
mail_from='test-owner@example.org', mail_from='test-owner@example.org',
template='averylongmessage') template='averylongmessage',
sourcemap={1: 'foo@example.org'})
client.send_messages([msg1]) client.send_messages([msg1])
ctrl.stop() ctrl.stop()
self.assertFalse(ctrl.handler.connected) self.assertFalse(ctrl.handler.connected)