aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2017-08-07 00:50:19 +0200
committerJ08nY2017-08-07 00:50:19 +0200
commit59ec076d04340245101de98633705d312374d9fe (patch)
tree8614919b84fa1f2d6cc3edeb39f197bd7bfe518b
parent570dfe8007d21593816d90df21f9f4fa25a7dae3 (diff)
downloadmailman-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.py2
-rw-r--r--src/mailman_pgp/commands/tests/test_key.py9
-rw-r--r--src/mailman_pgp/workflows/base.py43
-rw-r--r--src/mailman_pgp/workflows/key_change.py8
-rw-r--r--src/mailman_pgp/workflows/key_confirm.py17
-rw-r--r--src/mailman_pgp/workflows/key_revoke.py12
-rw-r--r--src/mailman_pgp/workflows/key_set.py9
-rw-r--r--src/mailman_pgp/workflows/subscription.py41
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')