diff options
| author | J08nY | 2017-08-06 02:30:57 +0200 |
|---|---|---|
| committer | J08nY | 2017-08-06 02:30:57 +0200 |
| commit | b56debf2d3db0732e6fa4a3d22ecaaae78fc5b65 (patch) | |
| tree | 0fc2ae11bf353d0da9f52f7d7c3dc5100936a51a | |
| parent | 66f1510d1a38c10944a13665e1b7f9ecb14a8d8f (diff) | |
| download | mailman-pgp-b56debf2d3db0732e6fa4a3d22ecaaae78fc5b65.tar.gz mailman-pgp-b56debf2d3db0732e6fa4a3d22ecaaae78fc5b65.tar.zst mailman-pgp-b56debf2d3db0732e6fa4a3d22ecaaae78fc5b65.zip | |
| -rw-r--r-- | src/mailman_pgp/commands/eml_key.py | 2 | ||||
| -rw-r--r-- | src/mailman_pgp/commands/tests/test_key.py | 2 | ||||
| -rw-r--r-- | src/mailman_pgp/workflows/key_change.py | 15 | ||||
| -rw-r--r-- | src/mailman_pgp/workflows/key_confirm.py (renamed from src/mailman_pgp/workflows/pubkey.py) | 73 | ||||
| -rw-r--r-- | src/mailman_pgp/workflows/key_set.py | 79 | ||||
| -rw-r--r-- | src/mailman_pgp/workflows/mod_approval.py | 74 | ||||
| -rw-r--r-- | src/mailman_pgp/workflows/subscription.py | 21 | ||||
| -rw-r--r-- | src/mailman_pgp/workflows/tests/test_base.py | 4 | ||||
| -rw-r--r-- | src/mailman_pgp/workflows/tests/test_mod_approval.py | 13 |
9 files changed, 202 insertions, 81 deletions
diff --git a/src/mailman_pgp/commands/eml_key.py b/src/mailman_pgp/commands/eml_key.py index 2bc00c7..417fd95 100644 --- a/src/mailman_pgp/commands/eml_key.py +++ b/src/mailman_pgp/commands/eml_key.py @@ -41,7 +41,7 @@ from mailman_pgp.utils.pgp import key_usable from mailman_pgp.workflows.key_change import (CHANGE_CONFIRM_REQUEST, KeyChangeModWorkflow, KeyChangeWorkflow) -from mailman_pgp.workflows.pubkey import CONFIRM_REQUEST +from mailman_pgp.workflows.key_confirm import CONFIRM_REQUEST def _cmd_set(pgp_list, mlist, msg, msgdata, arguments, results): diff --git a/src/mailman_pgp/commands/tests/test_key.py b/src/mailman_pgp/commands/tests/test_key.py index 900af7b..f6e4edf 100644 --- a/src/mailman_pgp/commands/tests/test_key.py +++ b/src/mailman_pgp/commands/tests/test_key.py @@ -41,7 +41,7 @@ from mailman_pgp.pgp.wrapper import PGPWrapper from mailman_pgp.testing.layers import PGPConfigLayer from mailman_pgp.testing.pgp import load_key from mailman_pgp.workflows.key_change import CHANGE_CONFIRM_REQUEST -from mailman_pgp.workflows.pubkey import CONFIRM_REQUEST +from mailman_pgp.workflows.key_confirm import CONFIRM_REQUEST from mailman_pgp.workflows.subscription import OpenSubscriptionPolicy diff --git a/src/mailman_pgp/workflows/key_change.py b/src/mailman_pgp/workflows/key_change.py index 8536304..fce7b71 100644 --- a/src/mailman_pgp/workflows/key_change.py +++ b/src/mailman_pgp/workflows/key_change.py @@ -32,7 +32,8 @@ 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 -from mailman_pgp.workflows.mod_approval import ModeratorApprovalMixin +from mailman_pgp.workflows.mod_approval import ( + ModeratorKeyChangeApprovalMixin) CHANGE_CONFIRM_REQUEST = """\ ---------- @@ -150,10 +151,20 @@ class KeyChangeWorkflow(KeyChangeBase): @public @implementer(IWorkflow) -class KeyChangeModWorkflow(KeyChangeBase, ModeratorApprovalMixin): +class KeyChangeModWorkflow(KeyChangeBase, ModeratorKeyChangeApprovalMixin): name = 'pgp-key-change-mod-workflow' description = '' initial_state = 'prepare' + save_attributes = ( + 'approved', + 'address_key', + 'pubkey_key' + ) + + def __init__(self, mlist, pgp_address=None, pubkey=None, + pre_approved=False): + KeyChangeBase.__init__(self, mlist, pgp_address, pubkey) + ModeratorKeyChangeApprovalMixin.__init__(self, pre_approved) def _step_prepare(self): self.push('do_change') diff --git a/src/mailman_pgp/workflows/pubkey.py b/src/mailman_pgp/workflows/key_confirm.py index 65ea74d..b8ac51e 100644 --- a/src/mailman_pgp/workflows/pubkey.py +++ b/src/mailman_pgp/workflows/key_confirm.py @@ -1,6 +1,23 @@ +# Copyright (C) 2017 Jan Jancar +# +# This file is a part of the Mailman PGP plugin. +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see <http://www.gnu.org/licenses/>. + +"""""" from mailman.email.message import UserNotification from mailman.interfaces.subscriptions import TokenOwner -from pgpy import PGPKey from public import public from mailman_pgp.database import transaction @@ -9,13 +26,6 @@ from mailman_pgp.model.list import PGPMailingList from mailman_pgp.pgp.wrapper import PGPWrapper from mailman_pgp.utils.email import copy_headers -KEY_REQUEST = """\ ----------- -TODO: this is a pgp enabled list. -We need your pubkey. -Reply to this message with it as a PGP/MIME(preferred) or inline. -----------""" - CONFIRM_REQUEST = """\ ---------- TODO: this is a pgp enabled list. @@ -29,53 +39,6 @@ Token: {} @public -class SetPubkeyMixin: - def __init__(self, pubkey=None): - self.pubkey = pubkey - - @property - def pubkey_key(self): - if self.pubkey is None: - return None - return str(self.pubkey) - - @pubkey_key.setter - def pubkey_key(self, value): - if value is not None: - self.pubkey, _ = PGPKey.from_blob(value) - else: - self.pubkey = None - - def _step_pubkey_checks(self): - pgp_address = PGPAddress.for_address(self.address) - assert pgp_address is not None - - if self.pubkey is None: - if pgp_address.key is None: - self.push('send_key_request') - else: - with transaction(): - pgp_address.key = self.pubkey - - def _step_send_key_request(self): - self._set_token(TokenOwner.subscriber) - self.push('receive_key') - self.save() - request_address = self.mlist.request_address - email_address = self.address.email - msg = UserNotification(email_address, request_address, - 'key set {}'.format(self.token), - KEY_REQUEST) - msg.send(self.mlist, add_precedence=False) - # Now we wait for the confirmation. - raise StopIteration - - def _step_receive_key(self): - self._restore_subscriber() - self._set_token(TokenOwner.no_one) - - -@public class ConfirmPubkeyMixin: def __init__(self, pre_confirmed=False): self.pubkey_confirmed = pre_confirmed diff --git a/src/mailman_pgp/workflows/key_set.py b/src/mailman_pgp/workflows/key_set.py new file mode 100644 index 0000000..e76e299 --- /dev/null +++ b/src/mailman_pgp/workflows/key_set.py @@ -0,0 +1,79 @@ +# Copyright (C) 2017 Jan Jancar +# +# This file is a part of the Mailman PGP plugin. +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see <http://www.gnu.org/licenses/>. + +"""""" +from mailman.email.message import UserNotification +from mailman.interfaces.subscriptions import TokenOwner +from pgpy import PGPKey +from public import public + +from mailman_pgp.database import transaction +from mailman_pgp.model.address import PGPAddress + +KEY_REQUEST = """\ +---------- +TODO: this is a pgp enabled list. +We need your pubkey. +Reply to this message with it as a PGP/MIME(preferred) or inline. +----------""" + + +@public +class SetPubkeyMixin: + def __init__(self, pubkey=None): + self.pubkey = pubkey + + @property + def pubkey_key(self): + if self.pubkey is None: + return None + return str(self.pubkey) + + @pubkey_key.setter + def pubkey_key(self, value): + if value is not None: + self.pubkey, _ = PGPKey.from_blob(value) + else: + self.pubkey = None + + def _step_pubkey_checks(self): + pgp_address = PGPAddress.for_address(self.address) + assert pgp_address is not None + + if self.pubkey is None: + if pgp_address.key is None: + self.push('send_key_request') + else: + with transaction(): + pgp_address.key = self.pubkey + + def _step_send_key_request(self): + self._set_token(TokenOwner.subscriber) + self.push('receive_key') + self.save() + request_address = self.mlist.request_address + email_address = self.address.email + msg = UserNotification(email_address, request_address, + 'key set {}'.format(self.token), + KEY_REQUEST) + msg.send(self.mlist, add_precedence=False) + # Now we wait for the confirmation. + raise StopIteration + + def _step_receive_key(self): + self._restore_subscriber() + self._set_token(TokenOwner.no_one) diff --git a/src/mailman_pgp/workflows/mod_approval.py b/src/mailman_pgp/workflows/mod_approval.py index 90edf4c..f610c4c 100644 --- a/src/mailman_pgp/workflows/mod_approval.py +++ b/src/mailman_pgp/workflows/mod_approval.py @@ -17,40 +17,77 @@ """""" import copy +from enum import Enum from mailman.email.message import UserNotification +from mailman.interfaces.pending import IPendings from mailman.interfaces.subscriptions import TokenOwner from public import public +from zope.component import getUtility from mailman_pgp.pgp.mime import MIMEWrapper from mailman_pgp.utils.email import overwrite_message -MOD_APPROVAL_REQUEST = """\ +SUBSCRIPTION_MOD_REQUEST = """\ ---------- TODO: this is a pgp enabled list. -A subscriber with address {} requested a change of his key. +A user with address {address} requested subscription His new key is attached to this message. -Fingerprint: {} +Fingerprint: {new_fpr} ---------- """ +KEY_CHANGE_MOD_REQUEST = """\ +---------- +TODO: this is a pgp enabled list. +A subscriber with address {address} requested a change of his key. +His new key is attached to this message. + +Old key fingerprint: {old_fpr} +New key fingerprint: {new_fpr} +---------- +""" + + +@public +class WhichApproval(Enum): + subscription = 1 + key_change = 2 + @public class ModeratorApprovalMixin: + def __init__(self, approval_type, pre_approved=False): + self.approved = pre_approved + self._approval_type = approval_type + def _step_mod_approval(self): - self.push('get_approval') + if not self.approved: + self.push('get_approval') def _step_get_approval(self): self._pend(TokenOwner.moderator) - self.push('receive_confirmation') + self.push('receive_mod_confirmation') self.save() + params = {'mlist': self.mlist.fqdn_listname, + 'address': self.pgp_address.email} + + if self._approval_type is WhichApproval.subscription: + name = 'subscription' + body = SUBSCRIPTION_MOD_REQUEST + params['old_fpr'] = params['new_fpr'] = self.pubkey.fingerprint + else: + name = 'key change' + body = KEY_CHANGE_MOD_REQUEST + params['old_fpr'] = self.pgp_address.key_fingerprint + params['new_fpr'] = self.pubkey.fingerprint + if self.mlist.admin_immed_notify: - subject = 'New key change request from {}'.format( - self.pgp_address.email) - text = MOD_APPROVAL_REQUEST.format(self.pgp_address.email, - self.pubkey.fingerprint) + subject = 'New {} request from {}'.format(name, + self.pgp_address.email) + text = body.format(**params) msg = UserNotification( self.mlist.owner_address, self.mlist.owner_address, subject, text, self.mlist.preferred_language) @@ -60,3 +97,22 @@ class ModeratorApprovalMixin: overwrite_message(msg, out) out.send(self.mlist) raise StopIteration + + def _step_receive_mod_confirmation(self): + pendings = getUtility(IPendings) + if self.token is not None: + pendings.confirm(self.token) + self.token = None + self.token_owner = TokenOwner.no_one + + +@public +class ModeratorSubApprovalMixin(ModeratorApprovalMixin): + def __init__(self, pre_approved=False): + super().__init__(WhichApproval.subscription, pre_approved) + + +@public +class ModeratorKeyChangeApprovalMixin(ModeratorApprovalMixin): + def __init__(self, pre_approved=False): + super().__init__(WhichApproval.key_change, pre_approved) diff --git a/src/mailman_pgp/workflows/subscription.py b/src/mailman_pgp/workflows/subscription.py index 809b7cb..d5803c2 100644 --- a/src/mailman_pgp/workflows/subscription.py +++ b/src/mailman_pgp/workflows/subscription.py @@ -19,13 +19,15 @@ from mailman.core.i18n import _ from mailman.interfaces.workflows import ISubscriptionWorkflow -from mailman.workflows.common import (ConfirmationMixin, ModerationMixin, - SubscriptionBase, VerificationMixin) +from mailman.workflows.common import (ConfirmationMixin, SubscriptionBase, + VerificationMixin) from public import public from zope.interface import implementer from mailman_pgp.workflows.base import PGPMixin -from mailman_pgp.workflows.pubkey import ConfirmPubkeyMixin, SetPubkeyMixin +from mailman_pgp.workflows.key_confirm import ConfirmPubkeyMixin +from mailman_pgp.workflows.key_set import SetPubkeyMixin +from mailman_pgp.workflows.mod_approval import ModeratorSubApprovalMixin @public @@ -112,7 +114,7 @@ class ConfirmSubscriptionPolicy(SubscriptionBase, VerificationMixin, @public @implementer(ISubscriptionWorkflow) class ModerationSubscriptionPolicy(SubscriptionBase, VerificationMixin, - ModerationMixin, SetPubkeyMixin, + ModeratorSubApprovalMixin, SetPubkeyMixin, ConfirmPubkeyMixin, PGPMixin): """""" @@ -136,14 +138,14 @@ class ModerationSubscriptionPolicy(SubscriptionBase, VerificationMixin, pubkey_pre_confirmed=False): SubscriptionBase.__init__(self, mlist, subscriber) VerificationMixin.__init__(self, pre_verified=pre_verified) - ModerationMixin.__init__(self, pre_approved=pre_approved) + ModeratorSubApprovalMixin.__init__(self, pre_approved=pre_approved) SetPubkeyMixin.__init__(self, pubkey=pubkey) ConfirmPubkeyMixin.__init__(self, pre_confirmed=pubkey_pre_confirmed) PGPMixin.__init__(self) def _step_prepare(self): self.push('do_subscription') - self.push('moderation_checks') + self.push('mod_approval') self.push('pubkey_confirmation') self.push('pubkey_checks') self.push('pgp_prepare') @@ -154,7 +156,8 @@ class ModerationSubscriptionPolicy(SubscriptionBase, VerificationMixin, @public @implementer(ISubscriptionWorkflow) class ConfirmModerationSubscriptionPolicy(SubscriptionBase, VerificationMixin, - ConfirmationMixin, ModerationMixin, + ConfirmationMixin, + ModeratorSubApprovalMixin, SetPubkeyMixin, ConfirmPubkeyMixin, PGPMixin): """""" @@ -181,14 +184,14 @@ class ConfirmModerationSubscriptionPolicy(SubscriptionBase, VerificationMixin, SubscriptionBase.__init__(self, mlist, subscriber) VerificationMixin.__init__(self, pre_verified=pre_verified) ConfirmationMixin.__init__(self, pre_confirmed=pre_confirmed) - ModerationMixin.__init__(self, pre_approved=pre_approved) + ModeratorSubApprovalMixin.__init__(self, pre_approved=pre_approved) SetPubkeyMixin.__init__(self, pubkey=pubkey) ConfirmPubkeyMixin.__init__(self, pre_confirmed=pubkey_pre_confirmed) PGPMixin.__init__(self) def _step_prepare(self): self.push('do_subscription') - self.push('moderation_checks') + self.push('mod_approval') self.push('pubkey_confirmation') self.push('pubkey_checks') self.push('pgp_prepare') diff --git a/src/mailman_pgp/workflows/tests/test_base.py b/src/mailman_pgp/workflows/tests/test_base.py index 5273939..440068c 100644 --- a/src/mailman_pgp/workflows/tests/test_base.py +++ b/src/mailman_pgp/workflows/tests/test_base.py @@ -37,8 +37,8 @@ from mailman_pgp.pgp.wrapper import PGPWrapper from mailman_pgp.testing.layers import PGPConfigLayer from mailman_pgp.testing.pgp import load_key from mailman_pgp.workflows.base import (PGPMixin) -from mailman_pgp.workflows.pubkey import (ConfirmPubkeyMixin, KEY_REQUEST, - SetPubkeyMixin) +from mailman_pgp.workflows.key_confirm import ConfirmPubkeyMixin +from mailman_pgp.workflows.key_set import KEY_REQUEST, SetPubkeyMixin class PubkeyMixinTestSetup(): diff --git a/src/mailman_pgp/workflows/tests/test_mod_approval.py b/src/mailman_pgp/workflows/tests/test_mod_approval.py index 49e4204..7d57a9b 100644 --- a/src/mailman_pgp/workflows/tests/test_mod_approval.py +++ b/src/mailman_pgp/workflows/tests/test_mod_approval.py @@ -33,14 +33,23 @@ from mailman_pgp.pgp.wrapper import PGPWrapper from mailman_pgp.testing.layers import PGPConfigLayer from mailman_pgp.testing.pgp import load_key from mailman_pgp.workflows.key_change import KeyChangeBase -from mailman_pgp.workflows.mod_approval import ModeratorApprovalMixin +from mailman_pgp.workflows.mod_approval import ( + ModeratorKeyChangeApprovalMixin) @implementer(IWorkflow) -class PGPTestWorkflow(KeyChangeBase, ModeratorApprovalMixin): +class PGPTestWorkflow(KeyChangeBase, ModeratorKeyChangeApprovalMixin): name = 'test-workflow' description = '' initial_state = 'mod_approval' + save_attributes = ( + 'approved', + ) + + def __init__(self, mlist, pgp_address=None, pubkey=None, + pre_approved=False): + KeyChangeBase.__init__(self, mlist, pgp_address, pubkey) + ModeratorKeyChangeApprovalMixin.__init__(self, pre_approved) class TestModeratorApprovalMixin(TestCase): |
