Пример #1
0
 def test_moderation_checks_moderated_list(self):
     # The unsubscription policy requires moderation.
     self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
     workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
     workflow.run_thru('confirmation_checks')
     with patch.object(workflow, '_step_moderation_checks') as step:
         next(workflow)
         step.assert_called_once_with()
Пример #2
0
 def test_moderation_checks_approval_required(self):
     # The moderator must approve the subscription request.
     self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
     workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
     workflow.run_thru('moderation_checks')
     with patch.object(workflow, '_step_get_moderator_approval') as step:
         next(workflow)
     step.assert_called_once_with()
Пример #3
0
 def test_send_confirmation_checks_confirm_list(self):
     # The unsubscription policy requires user confirmation and the
     # unsubscription is not pre-confirmed.
     self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
     workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
     workflow.run_thru('confirmation_checks')
     with patch.object(workflow, '_step_send_confirmation') as step:
         next(workflow)
     step.assert_called_once_with()
Пример #4
0
 def test_confirmation_checks_open_list(self):
     # An unsubscription from an open list does not need to be confirmed or
     # moderated.
     self._mlist.unsubscription_policy = SubscriptionPolicy.open
     workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
     workflow.run_thru('confirmation_checks')
     with patch.object(workflow, '_step_do_unsubscription') as step:
         next(workflow)
     step.assert_called_once_with()
Пример #5
0
 def test_confirmation_checks_no_user_confirmation_needed(self):
     # An unsubscription from a list which does not need user confirmation
     # skips to the moderation checks.
     self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
     workflow = UnSubscriptionWorkflow(self._mlist, self.anne,
                                       pre_confirmed=True)
     workflow.run_thru('confirmation_checks')
     with patch.object(workflow, '_step_moderation_checks') as step:
         next(workflow)
     step.assert_called_once_with()
Пример #6
0
 def test_confirmation_checks_confirm_pre_confirmed(self):
     # The unsubscription policy requires user-confirmation, but their
     # unsubscription is pre-confirmed. Since moderation is not reuqired,
     # the user will be immediately unsubscribed.
     self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
     workflow = UnSubscriptionWorkflow(
         self._mlist, self.anne, pre_confirmed=True)
     workflow.run_thru('confirmation_checks')
     with patch.object(workflow, '_step_do_unsubscription') as step:
         next(workflow)
     step.assert_called_once_with()
Пример #7
0
 def test_confirmation_checks_confirm_then_moderate_pre_confirmed(self):
     # The unsubscription policy requires user confirmation, but their
     # unsubscription is pre-confirmed. Since moderation is required, that
     # check will be performed.
     self._mlist.unsubscription_policy = (
         SubscriptionPolicy.confirm_then_moderate)
     workflow = UnSubscriptionWorkflow(
         self._mlist, self.anne, pre_confirmed=True)
     workflow.run_thru('confirmation_checks')
     with patch.object(workflow, '_step_do_unsubscription') as step:
         next(workflow)
     step.assert_called_once_with()
Пример #8
0
 def test_do_confirmation_nonmember_final_step(self):
     # Attempt to confirm the unsubscription of a member who has already
     # been unsubscribed.
     self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
     workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
     list(workflow)
     # Anne is a member.
     member = self._mlist.regular_members.get_member(self._anne)
     self.assertIsNotNone(member)
     self.assertEqual(member, workflow.member)
     # The token is owned by the subscriber.
     self.assertIsNotNone(workflow.token)
     self.assertEqual(workflow.token_owner, TokenOwner.subscriber)
     # Confirm.
     confirm_workflow = UnSubscriptionWorkflow(self._mlist)
     confirm_workflow.token = workflow.token
     confirm_workflow.restore()
     confirm_workflow.run_until('do_unsubscription')
     self.assertEqual(member, confirm_workflow.member)
     # Unsubscribe Anne out of band.
     member.unsubscribe()
     list(confirm_workflow)
     self.assertIsNone(confirm_workflow.member)
     # No further token is needed.
     self.assertIsNone(confirm_workflow.token)
     self.assertEqual(confirm_workflow.token_owner, TokenOwner.no_one)
Пример #9
0
    def test_get_moderator_approval_notifies_moderators(self):
        # When the unsubscription is held for moderator approval, and the list
        # is so configured, a notification is sent to the list moderators.
        self._mlist.admin_immed_notify = True
        self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
        workflow = UnSubscriptionWorkflow(self._mlist,
                                          self.anne,
                                          pre_confirmed=True)
        # Consume the entire state machine.
        list(workflow)
        items = get_queue_messages('virgin', expected_count=1)
        message = items[0].msg
        self.assertEqual(message['From'], '*****@*****.**')
        self.assertEqual(message['To'], '*****@*****.**')
        self.assertEqual(
            message['Subject'],
            'New unsubscription request to Test from [email protected]')
        self.assertEqual(
            message.get_payload(), """\
Your authorization is required for a mailing list unsubscription
request approval:

    For:  [email protected]
    List: [email protected]
""")
        # The state machine stopped at the moderator approval so there will be
        # one token still in the database.
        self._expected_pendings_count = 1
Пример #10
0
 def test_user_is_subscribed_to_unsubscribe(self):
     # A user must be subscribed to a list when trying to unsubscribe.
     addr = self._user_manager.create_address('*****@*****.**')
     addr.verfied_on = now()
     workflow = UnSubscriptionWorkflow(self._mlist, addr)
     self.assertRaises(AssertionError, workflow.run_thru,
                       'subscription_checks')
Пример #11
0
 def test_do_unsusbcription(self):
     # An open unsubscription policy means the user gets unsubscribed to
     # the mailing list without any further confirmations or approvals.
     self._mlist.unsubscription_policy = SubscriptionPolicy.open
     workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
     list(workflow)
     member = self._mlist.regular_members.get_member(self._anne)
     self.assertIsNone(member)
Пример #12
0
 def test_pended_data(self):
     # Test there is a Pendable object associated with a held
     # unsubscription request and it has some valid data associated with
     # it.
     self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
     workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
     with suppress(StopIteration):
         workflow.run_thru('send_confirmation')
     self.assertIsNotNone(workflow.token)
     pendable = getUtility(IPendings).confirm(workflow.token, expunge=False)
     self.assertEqual(pendable['list_id'], 'test.example.com')
     self.assertEqual(pendable['email'], '*****@*****.**')
     self.assertEqual(pendable['display_name'], '')
     self.assertEqual(pendable['when'], '2005-08-01T07:49:23')
     self.assertEqual(pendable['token_owner'], 'subscriber')
     # The token is still in the database.
     self._expected_pendings_count = 1
Пример #13
0
 def test_confirmation_needed_and_pre_confirmed(self):
     # The subscription policy is 'confirm' but the subscription is
     # pre-confirmed so the moderation checks can be skipped.
     self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
     workflow = UnSubscriptionWorkflow(
         self._mlist, self.anne, pre_confirmed=True, pre_approved=True)
     list(workflow)
     # Anne was unsubscribed.
     self.assertIsNone(workflow.token)
     self.assertEqual(workflow.token_owner, TokenOwner.no_one)
     self.assertIsNone(workflow.member)
Пример #14
0
 def test_moderator_approves(self):
     # The workflow runs until moderator approval is required, at which
     # point the workflow is saved.  Once the moderator approves, the
     # workflow resumes and the user is unsubscribed.
     self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
     workflow = UnSubscriptionWorkflow(self._mlist,
                                       self.anne,
                                       pre_confirmed=True)
     # Run the entire workflow.
     list(workflow)
     # The user is currently subscribed to the mailing list.
     member = self._mlist.regular_members.get_member(self._anne)
     self.assertIsNotNone(member)
     self.assertIsNotNone(workflow.member)
     # The token is owned by the moderator.
     self.assertIsNotNone(workflow.token)
     self.assertEqual(workflow.token_owner, TokenOwner.moderator)
     # Create a new workflow with the previous workflow's save token, and
     # restore its state.  This models an approved un-sunscription request
     # and should result in the user getting subscribed.
     approved_workflow = UnSubscriptionWorkflow(self._mlist)
     approved_workflow.token = workflow.token
     approved_workflow.restore()
     list(approved_workflow)
     # Now the user is unsubscribed from the mailing list.
     member = self._mlist.regular_members.get_member(self._anne)
     self.assertIsNone(member)
     self.assertEqual(approved_workflow.member, member)
     # No further token is needed.
     self.assertIsNone(approved_workflow.token)
     self.assertEqual(approved_workflow.token_owner, TokenOwner.no_one)
Пример #15
0
 def test_do_confirmation_unsubscribes_address(self):
     # Unsubscriptions to the mailing list must be confirmed.  Once that's
     # done, the address is unsubscribed.
     address = self.anne.register('*****@*****.**')
     self._mlist.subscribe(address)
     self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
     workflow = UnSubscriptionWorkflow(self._mlist, address)
     list(workflow)
     # Bart is a member.
     member = self._mlist.regular_members.get_member(
         '*****@*****.**')
     self.assertIsNotNone(member)
     self.assertEqual(member, workflow.member)
     # The token is owned by the subscriber.
     self.assertIsNotNone(workflow.token)
     self.assertEqual(workflow.token_owner, TokenOwner.subscriber)
     # Confirm.
     confirm_workflow = UnSubscriptionWorkflow(self._mlist)
     confirm_workflow.token = workflow.token
     confirm_workflow.restore()
     list(confirm_workflow)
     # Bart is now unsubscribed.
     member = self._mlist.regular_members.get_member(
         '*****@*****.**')
     self.assertIsNone(member)
     # No further token is needed.
     self.assertIsNone(confirm_workflow.token)
     self.assertEqual(confirm_workflow.token_owner, TokenOwner.no_one)
Пример #16
0
 def test_get_moderator_approval_no_notifications(self):
     # When the unsubscription request is held for moderator approval, and
     # the list is so configured, a notification is sent to the list
     # moderators.
     self._mlist.admin_immed_notify = False
     self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
     workflow = UnSubscriptionWorkflow(
         self._mlist, self.anne, pre_confirmed=True)
     # Consume the entire state machine.
     list(workflow)
     get_queue_messages('virgin', expected_count=0)
     # The state machine stopped at the moderator approval so there will be
     # one token still in the database.
     self._expected_pendings_count = 1
Пример #17
0
 def test_do_unsubscription_pre_approved(self):
     # A moderation-requiring subscription policy plus a pre-approved
     # address means the user gets unsubscribed from the mailing list
     # without any further confirmation or approvals.
     self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
     workflow = UnSubscriptionWorkflow(self._mlist, self.anne,
                                       pre_approved=True)
     list(workflow)
     # Anne is now unsubscribed form the mailing list.
     member = self._mlist.regular_members.get_member(self._anne)
     self.assertIsNone(member)
     # No further token is needed.
     self.assertIsNone(workflow.token)
     self.assertEqual(workflow.token_owner, TokenOwner.no_one)
Пример #18
0
 def test_do_unsubscription_pre_approved_pre_confirmed(self):
     # A moderation-requiring unsubscription policy plus a pre-appvoed
     # address means the user gets unsubscribed to the mailing list without
     # any further confirmations or approvals.
     self._mlist.unsubscription_policy = (
         SubscriptionPolicy.confirm_then_moderate)
     workflow = UnSubscriptionWorkflow(self._mlist, self.anne,
                                       pre_approved=True,
                                       pre_confirmed=True)
     list(workflow)
     member = self._mlist.regular_members.get_member(self._anne)
     self.assertIsNone(member)
     # No further token is needed.
     self.assertIsNone(workflow.token)
     self.assertEqual(workflow.token_owner, TokenOwner.no_one)
Пример #19
0
 def test_do_unsubscription_cleanups(self):
     # Once the user is unsubscribed, the token and its associated pending
     # database record will be removed from the database.
     self._mlist.unsubscription_policy = SubscriptionPolicy.open
     workflow = UnSubscriptionWorkflow(self._mlist, self.anne,
                                       pre_approved=True,
                                       pre_confirmed=True)
     # Run the workflow.
     list(workflow)
     # Anne is now unsubscribed from the list.
     member = self._mlist.regular_members.get_member(self._anne)
     self.assertIsNone(member)
     # Workflow is done, so it has no token.
     self.assertIsNone(workflow.token)
     self.assertEqual(workflow.token_owner, TokenOwner.no_one)
Пример #20
0
 def test_get_moderator_approval_log_on_hold(self):
     # When the unsubscription is held for moderator approval, a message is
     # logged.
     mark = LogFileMark('mailman.subscribe')
     self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
     workflow = UnSubscriptionWorkflow(self._mlist,
                                       self.anne,
                                       pre_confirmed=True)
     # Run the entire workflow.
     list(workflow)
     self.assertIn(
         '[email protected]: held unsubscription request from [email protected]',
         mark.readline())
     # The state machine stopped at the moderator approval step so there
     # will be one token still in the database.
     self._expected_pendings_count = 1
Пример #21
0
 def test_send_confirmation(self):
     # A confirmation message gets sent when the unsubscription must be
     # confirmed.
     self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
     # Run the workflow to model the confirmation step.
     workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
     list(workflow)
     items = get_queue_messages('virgin', expected_count=1)
     message = items[0].msg
     token = workflow.token
     self.assertEqual(message['Subject'],
                      'confirm {}'.format(workflow.token))
     self.assertEqual(message['From'],
                      'test-confirm+{}@example.com'.format(token))
     # The state machine stopped at the member confirmation step so there
     # will be one token still in the database.
     self._expected_pendings_count = 1
Пример #22
0
 def test_send_confirmation(self):
     # A confirmation message gets sent when the unsubscription must be
     # confirmed.
     self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
     # Run the workflow to model the confirmation step.
     workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
     list(workflow)
     items = get_queue_messages('virgin', expected_count=1)
     message = items[0].msg
     token = workflow.token
     self.assertTrue(
         str(message['Subject']).startswith('Your confirmation is '
                                            'needed to leave the '))
     self.assertEqual(
         message['From'], 'test-confirm+{}@example.com'.format(token))
     # The confirmation message is not `Precedence: bulk`.
     self.assertIsNone(message['precedence'])
     # The confirmation message is `Auto-Submitted: auto-generated`.
     self.assertEqual(message['auto-submitted'], 'auto-generated')
     # The state machine stopped at the member confirmation step so there
     # will be one token still in the database.
     self._expected_pendings_count = 1
Пример #23
0
 def test_confirmation_needed_moderator_address(self):
     address = self.anne.register('*****@*****.**')
     self._mlist.subscribe(address)
     self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
     workflow = UnSubscriptionWorkflow(self._mlist, address)
     # Get moderator approval.
     list(workflow)
     approved_workflow = UnSubscriptionWorkflow(self._mlist)
     approved_workflow.token = workflow.token
     approved_workflow.restore()
     list(approved_workflow)
     self.assertEqual(approved_workflow.subscriber, address)
     # Anne was unsubscribed.
     self.assertIsNone(approved_workflow.token)
     self.assertEqual(approved_workflow.token_owner, TokenOwner.no_one)
     self.assertIsNone(approved_workflow.member)
     member = self._mlist.regular_members.get_member(
         '*****@*****.**')
     self.assertIsNone(member)
Пример #24
0
 def test_user_or_address_required(self):
     # The `subscriber` attribute must be a user or address that is provided
     # to the workflow.
     workflow = UnSubscriptionWorkflow(self._mlist)
     self.assertRaises(AssertionError, list, workflow)
Пример #25
0
 def test_start_state(self):
     # Test the workflow starts with no tokens or members.
     workflow = UnSubscriptionWorkflow(self._mlist)
     self.assertEqual(workflow.token_owner, TokenOwner.no_one)
     self.assertIsNone(workflow.token)
     self.assertIsNone(workflow.member)
Пример #26
0
 def test_prevent_confirmation_replay_attacks(self):
     # Ensure that if the workflow requires two confirmations, e.g. first
     # the user confirming their subscription, and then the moderator
     # approving it, that different tokens are used in these two cases.
     self._mlist.unsubscription_policy = (
         SubscriptionPolicy.confirm_then_moderate)
     workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
     # Run the state machine up to the first confirmation, and cache the
     # confirmation token.
     list(workflow)
     token = workflow.token
     # Anne is still a member of the mailing list.
     member = self._mlist.regular_members.get_member(self._anne)
     self.assertIsNotNone(member)
     self.assertIsNotNone(workflow.member)
     # The token is owned by the subscriber.
     self.assertIsNotNone(workflow.token)
     self.assertEqual(workflow.token_owner, TokenOwner.subscriber)
     # The old token will not work for moderator approval.
     moderator_workflow = UnSubscriptionWorkflow(self._mlist)
     moderator_workflow.token = token
     moderator_workflow.restore()
     list(moderator_workflow)
     # The token is owned by the moderator.
     self.assertIsNotNone(moderator_workflow.token)
     self.assertEqual(moderator_workflow.token_owner, TokenOwner.moderator)
     # While we wait for the moderator to approve the subscription, note
     # that there's a new token for the next steps.
     self.assertNotEqual(token, moderator_workflow.token)
     # The old token won't work.
     final_workflow = UnSubscriptionWorkflow(self._mlist)
     final_workflow.token = token
     self.assertRaises(LookupError, final_workflow.restore)
     # Running this workflow will fail.
     self.assertRaises(AssertionError, list, final_workflow)
     # Anne is still not unsubscribed.
     member = self._mlist.regular_members.get_member(self._anne)
     self.assertIsNotNone(member)
     self.assertIsNone(final_workflow.member)
     # However, if we use the new token, her unsubscription request will be
     # approved by the moderator.
     final_workflow.token = moderator_workflow.token
     final_workflow.restore()
     list(final_workflow)
     # And now Anne is unsubscribed.
     member = self._mlist.regular_members.get_member(self._anne)
     self.assertIsNone(member)
     # No further token is needed.
     self.assertIsNone(final_workflow.token)
     self.assertEqual(final_workflow.token_owner, TokenOwner.no_one)
Пример #27
0
 def test_subscription_checks_for_address(self):
     # subscription_checks must pass for IAddress subscribed as IUser.
     workflow = UnSubscriptionWorkflow(self._mlist,
                                       self.anne.preferred_address)
     workflow.run_thru('subscription_checks')
Пример #28
0
 def test_subscription_checks_for_user(self):
     # subscription_checks must pass for IUser subscribed as IAddress.
     member = subscribe(self._mlist, 'Bart')
     set_preferred(member.user)
     workflow = UnSubscriptionWorkflow(self._mlist, member.user)
     workflow.run_thru('subscription_checks')