diff options
| author | J08nY | 2017-08-07 00:50:19 +0200 |
|---|---|---|
| committer | J08nY | 2017-08-07 00:50:19 +0200 |
| commit | 59ec076d04340245101de98633705d312374d9fe (patch) | |
| tree | 8614919b84fa1f2d6cc3edeb39f197bd7bfe518b | |
| parent | 570dfe8007d21593816d90df21f9f4fa25a7dae3 (diff) | |
| download | mailman-pgp-feature/key-revocation.tar.gz mailman-pgp-feature/key-revocation.tar.zst mailman-pgp-feature/key-revocation.zip | |
| -rw-r--r-- | src/mailman_pgp/commands/eml_key.py | 2 | ||||
| -rw-r--r-- | src/mailman_pgp/commands/tests/test_key.py | 9 | ||||
| -rw-r--r-- | src/mailman_pgp/workflows/base.py | 43 | ||||
| -rw-r--r-- | src/mailman_pgp/workflows/key_change.py | 8 | ||||
| -rw-r--r-- | src/mailman_pgp/workflows/key_confirm.py | 17 | ||||
| -rw-r--r-- | src/mailman_pgp/workflows/key_revoke.py | 12 | ||||
| -rw-r--r-- | src/mailman_pgp/workflows/key_set.py | 9 | ||||
| -rw-r--r-- | src/mailman_pgp/workflows/subscription.py | 41 |
8 files changed, 96 insertions, 45 deletions
diff --git a/src/mailman_pgp/commands/eml_key.py b/src/mailman_pgp/commands/eml_key.py index 5c53699..447ecf4 100644 --- a/src/mailman_pgp/commands/eml_key.py +++ b/src/mailman_pgp/commands/eml_key.py @@ -179,6 +179,8 @@ def _cmd_confirm(pgp_list, mlist, msg, msgdata, arguments, results): for sig_subject in wrapped.get_signed(): if expecting in sig_subject: + with transaction(): + pgp_address.key_confirmed = True ISubscriptionManager(mlist).confirm(token) break else: diff --git a/src/mailman_pgp/commands/tests/test_key.py b/src/mailman_pgp/commands/tests/test_key.py index f6e4edf..1a128a1 100644 --- a/src/mailman_pgp/commands/tests/test_key.py +++ b/src/mailman_pgp/commands/tests/test_key.py @@ -987,8 +987,13 @@ class TestAfterSubscription(unittest.TestCase): mm_config.switchboards['command'].enqueue(message, listid='test.example.com') make_testable_runner(CommandRunner, 'command').run() - items = get_queue_messages('virgin', expected_count=1) - results_msg = items[0].msg + items = get_queue_messages('virgin', expected_count=2) + if (items[0].msg['Subject'] == + 'The results of your email commands'): # pragma: no cover + results_msg = items[0].msg + else: + results_msg = items[1].msg + #TODO: finish test self.assertIn('Key needs to be reset.', results_msg.get_payload()) diff --git a/src/mailman_pgp/workflows/base.py b/src/mailman_pgp/workflows/base.py index bffcf94..9fc5d58 100644 --- a/src/mailman_pgp/workflows/base.py +++ b/src/mailman_pgp/workflows/base.py @@ -16,7 +16,15 @@ # this program. If not, see <http://www.gnu.org/licenses/>. """""" +from datetime import timedelta + +from mailman.interfaces.pending import IPendings +from mailman.interfaces.subscriptions import TokenOwner +from mailman.utilities.datetime import now +from mailman.utilities.modules import abstract_component +from mailman.workflows.common import SubscriptionBase from public import public +from zope.component import getUtility from mailman_pgp.database import transaction from mailman_pgp.model.address import PGPAddress @@ -29,6 +37,8 @@ class PGPMixin: self.mlist = mlist self.pgp_list = PGPMailingList.for_list(mlist) self.pgp_address = pgp_address + if self.pgp_address is not None: + self.address = self.pgp_address.address @property def address_key(self): @@ -45,3 +55,36 @@ class PGPMixin: with transaction() as t: self.pgp_address = PGPAddress(self.address) t.add(self.pgp_address) + + def _step_restore_address(self): + self.pgp_address = PGPAddress.for_address(self.address) + + def _set_token(self, token_owner): + assert isinstance(token_owner, TokenOwner) + pendings = getUtility(IPendings) + if self.token is not None: + pendings.confirm(self.token) + self.token_owner = token_owner + if token_owner is TokenOwner.no_one: + self.token = None + return + + pendable = self.pendable_class()( + list_id=self.mlist.list_id, + email=self.address.email, + display_name=self.address.display_name, + when=now().replace(microsecond=0).isoformat(), + token_owner=token_owner.name, + ) + self.token = pendings.add(pendable, timedelta(days=3650)) + + +@public +@abstract_component +class PGPSubscriptionBase(SubscriptionBase, PGPMixin): + def __init__(self, mlist, subscriber=None, *, pgp_address=None): + SubscriptionBase.__init__(self, mlist, subscriber) + PGPMixin.__init__(self, mlist, pgp_address=pgp_address) + + def _step_restore_subscriber(self): + self._restore_subscriber() diff --git a/src/mailman_pgp/workflows/key_change.py b/src/mailman_pgp/workflows/key_change.py index b2fac65..1d07903 100644 --- a/src/mailman_pgp/workflows/key_change.py +++ b/src/mailman_pgp/workflows/key_change.py @@ -50,7 +50,7 @@ Token: {} class KeyChangeBase(Workflow, PGPMixin): save_attributes = ( 'address_key', - 'pubkey_key' + 'pubkey_key', ) def __init__(self, mlist, pgp_address=None, pubkey=None): @@ -105,11 +105,7 @@ class KeyChangeBase(Workflow, PGPMixin): raise StopIteration def _step_receive_confirmation(self): - pendings = getUtility(IPendings) - if self.token is not None: - pendings.confirm(self.token) - self.token = None - self.token_owner = TokenOwner.no_one + self._set_token(TokenOwner.no_one) def _step_do_change(self): with transaction(): diff --git a/src/mailman_pgp/workflows/key_confirm.py b/src/mailman_pgp/workflows/key_confirm.py index b8ac51e..0a38551 100644 --- a/src/mailman_pgp/workflows/key_confirm.py +++ b/src/mailman_pgp/workflows/key_confirm.py @@ -21,7 +21,6 @@ from mailman.interfaces.subscriptions import TokenOwner from public import public from mailman_pgp.database import transaction -from mailman_pgp.model.address import PGPAddress from mailman_pgp.model.list import PGPMailingList from mailman_pgp.pgp.wrapper import PGPWrapper from mailman_pgp.utils.email import copy_headers @@ -44,14 +43,13 @@ class ConfirmPubkeyMixin: self.pubkey_confirmed = pre_confirmed def _step_pubkey_confirmation(self): - pgp_address = PGPAddress.for_address(self.address) - assert pgp_address is not None + assert self.pgp_address is not None if self.pubkey_confirmed: with transaction(): - pgp_address.key_confirmed = True + self.pgp_address.key_confirmed = True else: - if not pgp_address.key_confirmed: + if not self.pgp_address.key_confirmed: self.push('send_key_confirm_request') def _step_send_key_confirm_request(self): @@ -59,17 +57,16 @@ class ConfirmPubkeyMixin: self.push('receive_key_confirmation') self.save() - pgp_address = PGPAddress.for_address(self.address) request_address = self.mlist.request_address email_address = self.address.email msg = UserNotification(email_address, request_address, 'key confirm {}'.format(self.token), CONFIRM_REQUEST.format( - pgp_address.key_fingerprint, + self.pgp_address.key_fingerprint, self.token)) pgp_list = PGPMailingList.for_list(self.mlist) wrapped = PGPWrapper(msg) - encrypted = wrapped.sign_encrypt(pgp_list.key, pgp_address.key) + encrypted = wrapped.sign_encrypt(pgp_list.key, self.pgp_address.key) msg.set_payload(encrypted.get_payload()) copy_headers(encrypted, msg, True) @@ -77,8 +74,4 @@ class ConfirmPubkeyMixin: raise StopIteration def _step_receive_key_confirmation(self): - self._restore_subscriber() self._set_token(TokenOwner.no_one) - with transaction(): - pgp_address = PGPAddress.for_address(self.address) - pgp_address.key_confirmed = True diff --git a/src/mailman_pgp/workflows/key_revoke.py b/src/mailman_pgp/workflows/key_revoke.py index 523e6df..7a7c071 100644 --- a/src/mailman_pgp/workflows/key_revoke.py +++ b/src/mailman_pgp/workflows/key_revoke.py @@ -16,6 +16,7 @@ # this program. If not, see <http://www.gnu.org/licenses/>. """""" +from mailman.interfaces.pending import IPendable from mailman.interfaces.workflows import IWorkflow from mailman.workflows.base import Workflow from public import public @@ -32,6 +33,14 @@ class KeyRevokeBase(Workflow, PGPMixin): Workflow.__init__(self) PGPMixin.__init__(self, mlist, pgp_address) + @classmethod + def pendable_class(cls): + @implementer(IPendable) + class Pendable(dict): + PEND_TYPE = cls.name + + return Pendable + @public @implementer(IWorkflow) @@ -43,7 +52,8 @@ class KeyRevokeWorkflow(KeyRevokeBase, SetPubkeyMixin, ConfirmPubkeyMixin, save_attributes = ( 'approved', 'address_key', - 'pubkey_key' + 'pubkey_key', + 'pubkey_confirmed' ) def __init__(self, mlist, pgp_address=None, pubkey=None, diff --git a/src/mailman_pgp/workflows/key_set.py b/src/mailman_pgp/workflows/key_set.py index e76e299..95e6e7c 100644 --- a/src/mailman_pgp/workflows/key_set.py +++ b/src/mailman_pgp/workflows/key_set.py @@ -22,7 +22,6 @@ from pgpy import PGPKey from public import public from mailman_pgp.database import transaction -from mailman_pgp.model.address import PGPAddress KEY_REQUEST = """\ ---------- @@ -51,15 +50,14 @@ class SetPubkeyMixin: self.pubkey = None def _step_pubkey_checks(self): - pgp_address = PGPAddress.for_address(self.address) - assert pgp_address is not None + assert self.pgp_address is not None if self.pubkey is None: - if pgp_address.key is None: + if self.pgp_address.key is None: self.push('send_key_request') else: with transaction(): - pgp_address.key = self.pubkey + self.pgp_address.key = self.pubkey def _step_send_key_request(self): self._set_token(TokenOwner.subscriber) @@ -75,5 +73,4 @@ class SetPubkeyMixin: raise StopIteration def _step_receive_key(self): - self._restore_subscriber() self._set_token(TokenOwner.no_one) diff --git a/src/mailman_pgp/workflows/subscription.py b/src/mailman_pgp/workflows/subscription.py index 0ef1358..2546f1e 100644 --- a/src/mailman_pgp/workflows/subscription.py +++ b/src/mailman_pgp/workflows/subscription.py @@ -19,12 +19,11 @@ from mailman.core.i18n import _ from mailman.interfaces.workflows import ISubscriptionWorkflow -from mailman.workflows.common import (ConfirmationMixin, SubscriptionBase, - VerificationMixin) +from mailman.workflows.common import (ConfirmationMixin, VerificationMixin) from public import public from zope.interface import implementer -from mailman_pgp.workflows.base import PGPMixin +from mailman_pgp.workflows.base import PGPMixin, PGPSubscriptionBase from mailman_pgp.workflows.key_confirm import ConfirmPubkeyMixin from mailman_pgp.workflows.key_set import SetPubkeyMixin from mailman_pgp.workflows.mod_approval import ModeratorSubApprovalMixin @@ -32,7 +31,7 @@ from mailman_pgp.workflows.mod_approval import ModeratorSubApprovalMixin @public @implementer(ISubscriptionWorkflow) -class OpenSubscriptionPolicy(SubscriptionBase, VerificationMixin, +class OpenSubscriptionPolicy(PGPSubscriptionBase, VerificationMixin, SetPubkeyMixin, ConfirmPubkeyMixin, PGPMixin): """""" @@ -54,7 +53,7 @@ class OpenSubscriptionPolicy(SubscriptionBase, VerificationMixin, def __init__(self, mlist, subscriber=None, *, pre_verified=False, pubkey=None, pubkey_pre_confirmed=False): - SubscriptionBase.__init__(self, mlist, subscriber) + PGPSubscriptionBase.__init__(self, mlist, subscriber) VerificationMixin.__init__(self, pre_verified=pre_verified) SetPubkeyMixin.__init__(self, pubkey=pubkey) ConfirmPubkeyMixin.__init__(self, pre_confirmed=pubkey_pre_confirmed) @@ -62,7 +61,9 @@ class OpenSubscriptionPolicy(SubscriptionBase, VerificationMixin, def _step_prepare(self): self.push('do_subscription') + self.push('restore_subscriber') self.push('pubkey_confirmation') + self.push('restore_address') self.push('pubkey_checks') self.push('create_address') self.push('verification_checks') @@ -71,9 +72,9 @@ class OpenSubscriptionPolicy(SubscriptionBase, VerificationMixin, @public @implementer(ISubscriptionWorkflow) -class ConfirmSubscriptionPolicy(SubscriptionBase, VerificationMixin, +class ConfirmSubscriptionPolicy(PGPSubscriptionBase, VerificationMixin, ConfirmationMixin, SetPubkeyMixin, - ConfirmPubkeyMixin, PGPMixin): + ConfirmPubkeyMixin): """""" name = 'pgp-policy-confirm' @@ -94,16 +95,17 @@ class ConfirmSubscriptionPolicy(SubscriptionBase, VerificationMixin, def __init__(self, mlist, subscriber=None, *, pre_verified=False, pre_confirmed=False, pubkey=None, pubkey_pre_confirmed=False): - SubscriptionBase.__init__(self, mlist, subscriber) + PGPSubscriptionBase.__init__(self, mlist, subscriber) VerificationMixin.__init__(self, pre_verified=pre_verified) ConfirmationMixin.__init__(self, pre_confirmed=pre_confirmed) SetPubkeyMixin.__init__(self, pubkey=pubkey) ConfirmPubkeyMixin.__init__(self, pre_confirmed=pubkey_pre_confirmed) - PGPMixin.__init__(self, mlist) def _step_prepare(self): self.push('do_subscription') + self.push('restore_subscriber') self.push('pubkey_confirmation') + self.push('restore_address') self.push('pubkey_checks') self.push('create_address') self.push('confirmation_checks') @@ -113,9 +115,9 @@ class ConfirmSubscriptionPolicy(SubscriptionBase, VerificationMixin, @public @implementer(ISubscriptionWorkflow) -class ModerationSubscriptionPolicy(SubscriptionBase, VerificationMixin, +class ModerationSubscriptionPolicy(PGPSubscriptionBase, VerificationMixin, ModeratorSubApprovalMixin, SetPubkeyMixin, - ConfirmPubkeyMixin, PGPMixin): + ConfirmPubkeyMixin): """""" name = 'pgp-policy-moderate' @@ -136,17 +138,18 @@ class ModerationSubscriptionPolicy(SubscriptionBase, VerificationMixin, def __init__(self, mlist, subscriber=None, *, pre_verified=False, pre_approved=False, pubkey=None, pubkey_pre_confirmed=False): - SubscriptionBase.__init__(self, mlist, subscriber) + PGPSubscriptionBase.__init__(self, mlist, subscriber) VerificationMixin.__init__(self, pre_verified=pre_verified) ModeratorSubApprovalMixin.__init__(self, pre_approved=pre_approved) SetPubkeyMixin.__init__(self, pubkey=pubkey) ConfirmPubkeyMixin.__init__(self, pre_confirmed=pubkey_pre_confirmed) - PGPMixin.__init__(self, mlist) def _step_prepare(self): self.push('do_subscription') + self.push('restore_subscriber') self.push('mod_approval') self.push('pubkey_confirmation') + self.push('restore_address') self.push('pubkey_checks') self.push('create_address') self.push('verification_checks') @@ -155,11 +158,11 @@ class ModerationSubscriptionPolicy(SubscriptionBase, VerificationMixin, @public @implementer(ISubscriptionWorkflow) -class ConfirmModerationSubscriptionPolicy(SubscriptionBase, VerificationMixin, +class ConfirmModerationSubscriptionPolicy(PGPSubscriptionBase, + VerificationMixin, ConfirmationMixin, ModeratorSubApprovalMixin, - SetPubkeyMixin, ConfirmPubkeyMixin, - PGPMixin): + SetPubkeyMixin, ConfirmPubkeyMixin): """""" name = 'pgp-policy-confirm-moderate' @@ -181,18 +184,20 @@ class ConfirmModerationSubscriptionPolicy(SubscriptionBase, VerificationMixin, def __init__(self, mlist, subscriber=None, *, pre_verified=False, pre_confirmed=False, pre_approved=False, pubkey=None, pubkey_pre_confirmed=False): - SubscriptionBase.__init__(self, mlist, subscriber) + PGPSubscriptionBase.__init__(self, mlist, subscriber) VerificationMixin.__init__(self, pre_verified=pre_verified) ConfirmationMixin.__init__(self, pre_confirmed=pre_confirmed) ModeratorSubApprovalMixin.__init__(self, pre_approved=pre_approved) SetPubkeyMixin.__init__(self, pubkey=pubkey) ConfirmPubkeyMixin.__init__(self, pre_confirmed=pubkey_pre_confirmed) - PGPMixin.__init__(self, mlist) def _step_prepare(self): self.push('do_subscription') + self.push('restore_subscriber') self.push('mod_approval') + self.push('restore_address') self.push('pubkey_confirmation') + self.push('restore_address') self.push('pubkey_checks') self.push('create_address') self.push('confirmation_checks') |
