Exemple #1
0
 def test_70af5a4e5790_digests(self):
     IDS_TO_DIGESTABLE = [
         (1, True),
         (2, False),
         (3, False),
         (4, True),
         ]
     mlist_table = sa.sql.table(
         'mailinglist',
         sa.sql.column('id', sa.Integer),
         sa.sql.column('digests_enabled', sa.Boolean)
         )
     # Downgrading.
     with transaction():
         for table_id, enabled in IDS_TO_DIGESTABLE:
             config.db.store.execute(mlist_table.insert().values(
                 id=table_id, digests_enabled=enabled))
     with transaction():
         alembic.command.downgrade(alembic_cfg, '47294d3a604')
         results = config.db.store.execute(
             'SELECT id, digestable FROM mailinglist').fetchall()
     self.assertEqual(results, IDS_TO_DIGESTABLE)
     # Upgrading.
     with transaction():
         alembic.command.upgrade(alembic_cfg, '70af5a4e5790')
     results = config.db.store.execute(
         'SELECT id, digests_enabled FROM mailinglist').fetchall()
     self.assertEqual(results, IDS_TO_DIGESTABLE)
Exemple #2
0
 def test_delete_orphans(self):
     # When users are deleted, their UIDs are generally not deleted.  We
     # never delete rows from that table in order to guarantee no
     # duplicates.  However, some external testing frameworks want to be
     # able to reset the UID table, so they can use this interface to do
     # so.  See LP: #1420083.
     #
     # Create some users.
     manager = getUtility(IUserManager)
     users_by_uid = {}
     with transaction():
         for i in range(10):
             user = manager.create_user()
             users_by_uid[user.user_id] = user
             # The testing infrastructure does not record the UIDs for new
             # user options, so do that now to mimic the real system.
             UID.record(user.user_id)
     # We now have 10 unique uids.
     self.assertEqual(len(users_by_uid), 10)
     # Now delete all the users.
     with transaction():
         for user in list(users_by_uid.values()):
             manager.delete_user(user)
     # There are still 10 unique uids in the database.
     self.assertEqual(UID.get_total_uid_count(), 10)
     # Cull the orphan UIDs.
     content, response = call_api(
         'http://localhost:9001/3.0/reserved/uids/orphans',
         method='DELETE')
     self.assertEqual(response.status, 204)
     # Now there are no uids in the table.
     config.db.abort()
     self.assertEqual(UID.get_total_uid_count(), 0)
Exemple #3
0
 def test_member_changes_preferred_address(self):
     with transaction():
         anne = self._usermanager.create_user('*****@*****.**')
         preferred = list(anne.addresses)[0]
         preferred.verified_on = now()
         anne.preferred_address = preferred
         self._mlist.subscribe(anne)
     # Take a look at Anne's current membership.
     content, response = call_api('http://*****:*****@example.com')
     self.assertEqual(
         entry_0['address'],
         'http://*****:*****@example.com')
     # Anne registers a new address and makes it her preferred address.
     # There are no changes to her membership.
     with transaction():
         new_preferred = anne.register('*****@*****.**')
         new_preferred.verified_on = now()
         anne.preferred_address = new_preferred
     # Take another look at Anne's current membership.
     content, response = call_api('http://*****:*****@example.com')
     self.assertEqual(
         entry_0['address'],
         'http://*****:*****@example.com')
Exemple #4
0
    def setUp(self):
        # Create a fake mailing list and message object
        self._msg = mfs("""\
To: [email protected]
From: [email protected]
Subject: Testing the test list
Message-ID: <ant>
X-Message-ID-Hash: MS6QLWERIJLGCRF44J7USBFDELMNT2BW

Tests are better than no tests
but the water deserves to be swum.
""")
        with transaction():
            self._mlist = create_list('*****@*****.**')
        # Set up a temporary directory for the prototype archiver so that it's
        # easier to clean up.
        self._tempdir = tempfile.mkdtemp()
        config.push('prototype', """
        [paths.testing]
        archive_dir: {0}
        """.format(self._tempdir))
        # Capture the structure of a maildir.
        self._expected_dir_structure = set(
            (os.path.join(config.ARCHIVE_DIR, path) for path in (
                'prototype',
                os.path.join('prototype', self._mlist.fqdn_listname),
                os.path.join('prototype', self._mlist.fqdn_listname, 'cur'),
                os.path.join('prototype', self._mlist.fqdn_listname, 'new'),
                os.path.join('prototype', self._mlist.fqdn_listname, 'tmp'),
                )))
        self._expected_dir_structure.add(config.ARCHIVE_DIR)
Exemple #5
0
 def test_absorb_addresses(self):
     # Absorbing the user absorbs all of the users addresses.  I.e. they
     # are relinked to the absorbing user.
     anne_preferred = self._anne.preferred_address
     with transaction():
         # This has to happen in a transaction so that both the user and
         # the preferences objects get valid ids.
         bart = self._manager.create_user('*****@*****.**', 'Bart Person')
         bart_secondary = self._manager.create_address(
             '*****@*****.**')
         bart.link(bart_secondary)
     # Absorb the Bart user into Anne.
     self._anne.absorb(bart)
     # Bart's primary and secondary addresses are now linked to Anne.
     anne_addresses = list(
         address.email for address in self._anne.addresses)
     self.assertIn('*****@*****.**', anne_addresses)
     self.assertIn('*****@*****.**', anne_addresses)
     # Anne's preferred address shouldn't change.
     self.assertEqual(self._anne.preferred_address, anne_preferred)
     # Check the reverse linkages by getting Bart's addresses from the user
     # manager.  They should both point back to the Anne user.
     self.assertEqual(
         self._manager.get_user('*****@*****.**'), self._anne)
     self.assertEqual(
         self._manager.get_user('*****@*****.**'), self._anne)
     # The Bart user has been deleted.
     self.assertIsNone(self._manager.get_user_by_id(bart.user_id))
Exemple #6
0
 def test_clear(self):
     header_matches = IHeaderMatchList(self._mlist)
     header_matches.append('Header', 'pattern')
     self.assertEqual(len(self._mlist.header_matches), 1)
     with transaction():
         header_matches.clear()
     self.assertEqual(len(self._mlist.header_matches), 0)
Exemple #7
0
 def test_transaction_abort_after_failing_subcommand(self):
     with transaction():
         mlist = create_list('*****@*****.**')
         mlist.volume = 5
         mlist.next_digest_number = 3
         mlist.digest_last_sent_at = now() - timedelta(days=60)
     testargs = ['mailman', 'digests', '-b', '-l', '*****@*****.**',
                 '--send']
     output = StringIO()
     with ExitStack() as resources:
         enter = resources.enter_context
         enter(patch('sys.argv', testargs))
         enter(patch('sys.stdout', output))
         # Force an exception in the subcommand.
         enter(patch('mailman.commands.cli_digests.maybe_send_digest_now',
                     side_effect=RuntimeError))
         # Everything is already initialized.
         enter(patch('mailman.bin.mailman.initialize'))
         with self.assertRaises(RuntimeError):
             main()
     # Clear the current transaction to force a database reload.
     config.db.abort()
     # The volume and number haven't changed.
     self.assertEqual(mlist.volume, 5)
     self.assertEqual(mlist.next_digest_number, 3)
Exemple #8
0
    def test_successful_login_updates_password(self):
        # Passlib supports updating the hash when the hash algorithm changes.
        # When a user logs in successfully, the password will be updated if
        # necessary.
        #
        # Start by hashing Anne's password with a different hashing algorithm
        # than the one that the REST runner uses by default during testing.
        config_file = os.path.join(config.VAR_DIR, 'passlib-tmp.config')
        with open(config_file, 'w') as fp:
            print("""\
[passlib]
schemes = hex_md5
""", file=fp)
        with configuration('passwords', configuration=config_file):
            with transaction():
                self.anne.password = config.password_context.encrypt('abc123')
                # Just ensure Anne's password is hashed correctly.
                self.assertEqual(self.anne.password,
                                 'e99a18c428cb38d5f260853678922e03')
        # Now, Anne logs in with a successful password.  This should change it
        # back to the plaintext hash.
        call_api('http://localhost:9001/3.0/users/1/login', {
                 'cleartext_password': '******',
                 })
        self.assertEqual(self.anne.password, '{plaintext}abc123')
 def test_lists_are_deleted_when_domain_is_deleted(self):
     # /domains/<domain> DELETE removes all associated mailing lists.
     with transaction():
         create_list("*****@*****.**")
     content, response = call_api("http://*****:*****@example.com"))
Exemple #10
0
 def test_bad_preferences_url(self):
     with transaction():
         subscribe(self._mlist, 'Anne')
     with self.assertRaises(HTTPError) as cm:
         call_api('http://*****:*****@example.com/preferences/bogus')
     self.assertEqual(cm.exception.code, 404)
Exemple #11
0
    def test_linked_nonmember_findable_after_posting(self):
        # Like above, a nonmember posts a message to the mailing list.  In
        # this case though, the nonmember already has a user record.  They are
        # findable through the /members/find API using a role of nonmember.
        with transaction():
            self._usermanager.create_user('*****@*****.**')
        self._go("""\
From: [email protected]
To: [email protected]
Subject: Nonmember post
Message-ID: <alpha>

Some text.
""")
        # Now use the REST API to try to find the nonmember.
        response, content = call_api(
            'http://*****:*****@example.com')
        self.assertEqual(
            nonmember['address'],
            'http://*****:*****@example.com')
        # There is a user key in the JSON data because the address had
        # previously been linked to a user record.
        self.assertEqual(nonmember['user'],
                         'http://localhost:9001/3.0/users/1')
Exemple #12
0
 def test_absorb_duplicates(self):
     # Duplicate memberships, where the list-id and role match, are
     # ignored.  Here we subscribe Anne to the test list as a member, and
     # Bart as both a member and an owner.  Anne's member membership
     # remains unchanged, but she gains an owner membership.
     with transaction():
         bart = self._manager.create_user('*****@*****.**')
         set_preferred(bart)
     self._mlist.subscribe(self._anne, MemberRole.member)
     self._mlist.subscribe(bart, MemberRole.member)
     self._mlist.subscribe(bart, MemberRole.owner)
     # There are now three memberships.
     all_members = list(self._manager.members)
     self.assertEqual(len(all_members), 3, all_members)
     # Do the absorption.
     self._anne.absorb(bart)
     # There are now only 2 memberships, both owned by Anne.
     all_members = list(self._manager.members)
     self.assertEqual(len(all_members), 2, all_members)
     memberships = set([
         (member.list_id, member.role, member.address.email)
         for member in all_members
         ])
     self.assertEqual(memberships, set([
         ('test.example.com', MemberRole.member, '*****@*****.**'),
         ('test.example.com', MemberRole.owner, '*****@*****.**'),
         ]))
Exemple #13
0
 def test_accept_by_moderator_clears_request_queue(self):
     # After accepting a message held for moderator approval, there are no
     # more requests to handle.
     #
     # We start with nothing in the queue.
     content, response = call_api(
         'http://*****:*****@example.com/requests')
     self.assertEqual(content['total_size'], 0)
     # Anne tries to subscribe to a list that only requests moderator
     # approval.
     with transaction():
         self._mlist.subscription_policy = SubscriptionPolicy.moderate
         token, token_owner, member = self._registrar.register(
             self._anne,
             pre_verified=True, pre_confirmed=True)
     # There's now one request in the queue, and it's waiting on moderator
     # approval.
     content, response = call_api(
         'http://*****:*****@example.com/requests')
     self.assertEqual(content['total_size'], 1)
     json = content['entries'][0]
     self.assertEqual(json['token_owner'], 'moderator')
     self.assertEqual(json['email'], '*****@*****.**')
     # The moderator approves the request.
     url = 'http://*****:*****@example.com/requests/{}'
     content, response = call_api(url.format(token), {'action': 'accept'})
     self.assertEqual(response.status, 204)
     # And now the request queue is empty.
     content, response = call_api(
         'http://*****:*****@example.com/requests')
     self.assertEqual(content['total_size'], 0)
Exemple #14
0
 def test_reject(self):
     # POST to the request to reject it.  This leaves a bounce message in
     # the virgin queue.
     with transaction():
         token, token_owner, member = self._registrar.register(self._anne)
     # Anne's subscription request got held.
     self.assertIsNone(member)
     # Clear out the virgin queue, which currently contains the
     # confirmation message sent to Anne.
     get_queue_messages('virgin')
     url = 'http://*****:*****@example.com/requests/{}'
     content, response = call_api(url.format(token), dict(
         action='reject',
         ))
     self.assertEqual(response.status, 204)
     # Anne is not a member.
     self.assertIsNone(self._mlist.members.get_member('*****@*****.**'))
     # The request URL no longer exists.
     with self.assertRaises(HTTPError) as cm:
         call_api(url.format(token), dict(
             action='reject',
             ))
     self.assertEqual(cm.exception.code, 404)
     # And the rejection message to Anne is now in the virgin queue.
     items = get_queue_messages('virgin')
     self.assertEqual(len(items), 1)
     message = items[0].msg
     self.assertEqual(message['From'], '*****@*****.**')
     self.assertEqual(message['To'], '*****@*****.**')
     self.assertEqual(message['Subject'],
                      'Request to mailing list "Ant" rejected')
Exemple #15
0
def reset_the_world():
    """Reset everything:

    * Clear out the database
    * Remove all residual queue and digest files
    * Clear the message store
    * Reset the global style manager

    This should be as thorough a reset of the system as necessary to keep
    tests isolated.
    """
    # Reset the database between tests.
    config.db._reset()
    # Remove any digest files.
    for dirpath, dirnames, filenames in os.walk(config.LIST_DATA_DIR):
        for filename in filenames:
            if filename.endswith('.mmdf'):
                os.remove(os.path.join(dirpath, filename))
    # Remove all residual queue files.
    for dirpath, dirnames, filenames in os.walk(config.QUEUE_DIR):
        for filename in filenames:
            os.remove(os.path.join(dirpath, filename))
    # Clear out messages in the message store.
    message_store = getUtility(IMessageStore)
    with transaction():
        for message in message_store.messages:
            message_store.delete_message(message['message-id'])
    # Reset the global style manager.
    getUtility(IStyleManager).populate()
    # Remove all dynamic header-match rules.
    config.chains['header-match'].flush()
Exemple #16
0
 def test_defer(self):
     # Defer the decision for some other moderator.
     with transaction():
         token, token_owner, member = self._registrar.register(self._anne)
     # Anne's subscription request got held.
     self.assertIsNone(member)
     url = 'http://*****:*****@example.com/requests/{}'
     content, response = call_api(url.format(token), dict(
         action='defer',
         ))
     self.assertEqual(response.status, 204)
     # Anne is not a member.
     self.assertIsNone(self._mlist.members.get_member('*****@*****.**'))
     # The request URL still exists.
     content, response = call_api(url.format(token), dict(
         action='defer',
         ))
     self.assertEqual(response.status, 204)
     # And now we can accept it.
     content, response = call_api(url.format(token), dict(
         action='accept',
         ))
     self.assertEqual(response.status, 204)
     # Anne is a member.
     self.assertEqual(
         self._mlist.members.get_member('*****@*****.**').address,
         self._anne)
     # The request URL no longer exists.
     with self.assertRaises(HTTPError) as cm:
         call_api(url.format(token), dict(
             action='accept',
             ))
     self.assertEqual(cm.exception.code, 404)
Exemple #17
0
 def test_member_ids_are_hex(self):
     with transaction():
         subscribe(self._mlist, 'Anne')
         subscribe(self._mlist, 'Bart')
     response, headers = call_api('http://localhost:9001/3.1/members')
     entries = response['entries']
     self.assertEqual(len(entries), 2)
     self.assertEqual(
       entries[0]['self_link'],
       'http://localhost:9001/3.1/members/00000000000000000000000000000001')
     self.assertEqual(
         entries[0]['member_id'],
         '00000000000000000000000000000001')
     self.assertEqual(
         entries[0]['user'],
         'http://localhost:9001/3.1/users/00000000000000000000000000000001')
     self.assertEqual(
       entries[1]['self_link'],
       'http://localhost:9001/3.1/members/00000000000000000000000000000002')
     self.assertEqual(
         entries[1]['member_id'],
         '00000000000000000000000000000002')
     self.assertEqual(
         entries[1]['user'],
         'http://localhost:9001/3.1/users/00000000000000000000000000000002')
 def test_get_digest_volume_frequency(self):
     with transaction():
         self._mlist.digest_volume_frequency = DigestFrequency.yearly
     resource, response = call_api(
         'http://localhost:9001/3.0/lists/ant.example.com/config'
         '/digest_volume_frequency')
     self.assertEqual(resource['digest_volume_frequency'], 'yearly')
 def test_get_digests_enabled(self):
     with transaction():
         self._mlist.digests_enabled = False
     resource, response = call_api(
         'http://localhost:9001/3.0/lists/ant.example.com/config'
         '/digests_enabled')
     self.assertFalse(resource['digests_enabled'])
Exemple #20
0
    def setUp(self):
        # Create a fake mailing list and message object.
        self._msg = mfs("""\
To: [email protected]
From: [email protected]
Subject: Testing the test list
Message-ID: <ant>
Message-ID-Hash: MS6QLWERIJLGCRF44J7USBFDELMNT2BW

Tests are better than no tests
but the water deserves to be swum.
""")
        with transaction():
            self._mlist = create_list('*****@*****.**')
        tempdir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, tempdir)
        # Here's the command to execute our fake MHonArc process.
        shutil.copy(
            resource_filename('mailman.archiving.tests', 'fake_mhonarc.py'),
            tempdir)
        self._output_file = os.path.join(tempdir, 'output.txt')
        command = '{} {} {}'.format(
            sys.executable,
            os.path.join(tempdir, 'fake_mhonarc.py'),
            self._output_file)
        # Write an external configuration file which points the command at our
        # fake MHonArc process.
        self._cfg = os.path.join(tempdir, 'mhonarc.cfg')
        with open(self._cfg, 'w', encoding='utf-8') as fp:
            print("""\
[general]
base_url: http://$hostname/archives/$fqdn_listname
command: {command}
""".format(command=command), file=fp)
Exemple #21
0
 def test_all_preferences(self):
     with transaction():
         member = subscribe(self._mlist, 'Anne')
         member.preferences.delivery_mode = DeliveryMode.summary_digests
     response, headers = call_api(
         'http://localhost:9001/3.1/members'
         '/00000000000000000000000000000001/all/preferences')
     self.assertEqual(response['delivery_mode'], 'summary_digests')
Exemple #22
0
 def test_delete_other_role(self):
     with transaction():
         subscribe(self._mlist, 'Anne', MemberRole.moderator)
     response, headers = call_api(
         'http://localhost:9001/3.0/members/1',
         method='DELETE')
     self.assertEqual(headers.status, 204)
     self.assertEqual(len(list(self._mlist.moderators.members)), 0)
Exemple #23
0
 def test_request_is_not_held_message(self):
     requests = IListRequests(self._mlist)
     with transaction():
         request_id = requests.hold_request(RequestType.subscription, 'foo')
     with self.assertRaises(HTTPError) as cm:
         call_api('http://localhost:9001/3.0/lists/ant.example.com'
                  '/held/{}'.format(request_id))
     self.assertEqual(cm.exception.code, 404)
 def test_get_goodbye_message_uri(self):
     with transaction():
         self._mlist.goodbye_message_uri = 'mailman:///goodbye.txt'
     resource, response = call_api(
         'http://localhost:9001/3.0/lists/ant.example.com/config'
         '/goodbye_message_uri')
     self.assertEqual(
         resource['goodbye_message_uri'], 'mailman:///goodbye.txt')
Exemple #25
0
 def test_unverify_bad_request(self):
     # Too many segments after /verify.
     with transaction():
         anne = getUtility(IUserManager).create_address('*****@*****.**')
         self.assertEqual(anne.verified_on, None)
     with self.assertRaises(HTTPError) as cm:
         call_api('http://*****:*****@example.com/unverify/foo', {})
     self.assertEqual(cm.exception.code, 400)
Exemple #26
0
 def test_address_user_id_is_hex(self):
     user_manager = getUtility(IUserManager)
     with transaction():
         user_manager.create_user('*****@*****.**', 'Anne')
     response, headers = call_api(
         'http://*****:*****@example.com')
     self.assertEqual(
         response['user'],
         'http://localhost:9001/3.1/users/00000000000000000000000000000001')
Exemple #27
0
 def setUp(self):
     # Create a user and link 10 addresses to that user.
     self.manager = getUtility(IUserManager)
     with transaction():
         anne = self.manager.create_user('*****@*****.**', 'Anne Person')
         for i in range(10):
             email = 'a{:02d}@example.com'.format(i)
             address = self.manager.create_address(email)
             anne.link(address)
Exemple #28
0
 def test_address_with_user(self):
     # An address which is already linked to a user has a 'user' key in the
     # JSON representation.
     with transaction():
         getUtility(IUserManager).create_user('*****@*****.**')
     json, headers = call_api(
         'http://*****:*****@example.com')
     self.assertEqual(headers['status'], '200')
     self.assertEqual(json['user'], 'http://localhost:9001/3.0/users/1')
Exemple #29
0
 def test_user_subresource_on_unlinked_address(self):
     # Trying to access the 'user' subresource on an address that is not
     # linked to a user will return a 404 error.
     with transaction():
         getUtility(IUserManager).create_address('*****@*****.**')
     with self.assertRaises(HTTPError) as cm:
         call_api(
             'http://*****:*****@example.com/user')
     self.assertEqual(cm.exception.code, 404)
Exemple #30
0
 def test_address_without_user(self):
     # The 'user' key is missing from the JSON representation of an address
     # with no linked user.
     with transaction():
         getUtility(IUserManager).create_address('*****@*****.**')
     json, headers = call_api(
         'http://*****:*****@example.com')
     self.assertEqual(headers['status'], '200')
     self.assertNotIn('user', json)
Exemple #31
0
 def test_get_a_url(self):
     with transaction():
         getUtility(ITemplateManager).set('list:user:notice:welcome',
                                          'ant.example.com',
                                          'http://example.com/welcome')
     json, response = call_api(
         'http://localhost:9001/3.1/lists/ant.example.com/uris'
         '/list:user:notice:welcome')
     self.assertEqual(response.status_code, 200)
     self.assertEqual(
         json, {
             'http_etag':
             '"36f8bef800cfd278f097c61c5892a34c0650f4aa"',
             'self_link': ('http://localhost:9001/3.1/lists/ant.example.com'
                           '/uris/list:user:notice:welcome'),
             'uri':
             'http://example.com/welcome',
         })
Exemple #32
0
 def test_accept(self):
     # POST to the request to accept it.
     with transaction():
         token, token_owner, member = self._registrar.register(self._anne)
     # Anne's subscription request got held.
     self.assertIsNone(member)
     url = 'http://*****:*****@example.com/requests/{}'
     content, response = call_api(url.format(token),
                                  dict(action='accept', ))
     self.assertEqual(response.status, 204)
     # Anne is a member.
     self.assertEqual(
         self._mlist.members.get_member('*****@*****.**').address,
         self._anne)
     # The request URL no longer exists.
     with self.assertRaises(HTTPError) as cm:
         call_api(url.format(token), dict(action='accept', ))
     self.assertEqual(cm.exception.code, 404)
Exemple #33
0
 def test_delete_user_twice(self):
     # You cannot DELETE a user twice, either by address or user id.
     with transaction():
         anne = getUtility(IUserManager).create_user(
             '*****@*****.**', 'Anne Person')
         user_id = anne.user_id
     content, response = call_api(
         'http://*****:*****@example.com',
         method='DELETE')
     self.assertEqual(response.status, 204)
     with self.assertRaises(HTTPError) as cm:
         call_api('http://*****:*****@example.com',
                  method='DELETE')
     self.assertEqual(cm.exception.code, 404)
     with self.assertRaises(HTTPError) as cm:
         call_api('http://localhost:9001/3.0/users/{}'.format(user_id),
                  method='DELETE')
     self.assertEqual(cm.exception.code, 404)
Exemple #34
0
 def setUp(self):
     self._mlist = create_list('*****@*****.**')
     # Add some owners, moderators, and members
     manager = getUtility(IUserManager)
     with transaction():
         anne = manager.create_address('*****@*****.**')
         bart = manager.create_address('*****@*****.**')
         cris = manager.create_address('*****@*****.**')
         dave = manager.create_address('*****@*****.**')
         self._mlist.subscribe(anne, MemberRole.member)
         self._mlist.subscribe(anne, MemberRole.owner)
         self._mlist.subscribe(bart, MemberRole.moderator)
         self._mlist.subscribe(bart, MemberRole.owner)
         self._mlist.subscribe(cris, MemberRole.moderator)
         self._mlist.subscribe(dave, MemberRole.member)
     self._inq = make_testable_runner(IncomingRunner, 'in')
     self._pipelineq = make_testable_runner(PipelineRunner, 'pipeline')
     self._outq = make_testable_runner(OutgoingRunner, 'out')
Exemple #35
0
 def test_address_added_to_user(self):
     # An address is added to a user record.
     user_manager = getUtility(IUserManager)
     with transaction():
         anne = user_manager.create_user('*****@*****.**')
     json, response = call_api(
         'http://*****:*****@example.com/addresses', {
             'email': '*****@*****.**',
         })
     self.assertIn('*****@*****.**',
                   [addr.email for addr in anne.addresses])
     self.assertEqual(response.status_code, 201)
     self.assertEqual(
         response.headers['location'],
         'http://*****:*****@example.org')
     # The address has no display name.
     anne_person = user_manager.get_address('*****@*****.**')
     self.assertEqual(anne_person.display_name, '')
Exemple #36
0
 def test_join_as_user_with_preferred_address(self):
     with transaction():
         anne = self._usermanager.create_user('*****@*****.**')
         _set_preferred(anne)
         self._mlist.subscribe(anne)
     content, response = call_api('http://*****:*****@example.com')
     self.assertEqual(
         entry_0['address'],
         'http://*****:*****@example.com')
     self.assertEqual(entry_0['list_id'], 'test.example.com')
Exemple #37
0
 def test_user_subresource_put(self):
     # By PUTing to the 'user' resource, you can change the user that an
     # address is linked to.
     user_manager = getUtility(IUserManager)
     with transaction():
         anne = user_manager.create_user('*****@*****.**', 'Anne')
         bart = user_manager.create_user(display_name='Bart')
     json, response = call_api(
         'http://*****:*****@example.com/user', {
             'user_id': bart.user_id.hex,
         },
         method='PUT')
     self.assertEqual(response.status_code, 200)
     self.assertEqual(anne.addresses, [])
     self.assertEqual([address.email for address in bart.addresses],
                      ['*****@*****.**'])
     self.assertEqual(bart,
                      user_manager.get_address('*****@*****.**').user)
Exemple #38
0
 def test_list_held_requests(self):
     # We can view all the held requests.
     with transaction():
         token_1, token_owner, member = self._registrar.register(self._anne)
         # Anne's subscription request got held.
         self.assertIsNotNone(token_1)
         self.assertIsNone(member)
         token_2, token_owner, member = self._registrar.register(self._bart)
         self.assertIsNotNone(token_2)
         self.assertIsNone(member)
     json, response = call_api(
         'http://*****:*****@example.com/requests')
     self.assertEqual(response.status_code, 200)
     self.assertEqual(json['total_size'], 2)
     tokens = set(entry['token'] for entry in json['entries'])
     self.assertEqual(tokens, {token_1, token_2})
     emails = set(entry['email'] for entry in json['entries'])
     self.assertEqual(emails, {'*****@*****.**', '*****@*****.**'})
Exemple #39
0
 def test_user_subresource_cannot_put_int(self):
     # If the address is not yet linked to a user, POSTing a user id to the
     # 'user' subresource links the address to the given user.  In
     # API 3.1, the user id must be the hex representation.
     user_manager = getUtility(IUserManager)
     with transaction():
         anne = user_manager.create_user('*****@*****.**', 'Anne')
         user_manager.create_address('*****@*****.**')
     with self.assertRaises(HTTPError) as cm:
         call_api(
             'http://*****:*****@example.com/user', {
                 'user_id': anne.user_id.int,
             },
             method='PUT')
     self.assertEqual(cm.exception.code, 400)
     self.assertEqual(
         cm.exception.reason, 'Invalid Parameter "user_id":'
         ' badly formed hexadecimal UUID string.')
Exemple #40
0
    def test_subject_encoding_error(self):
        # GL#383: messages with badly encoded Subject headers crash the REST
        # server.
        self._msg = mfs("""\
From: [email protected]
To: [email protected]
Subject: =?GB2312?B?saa9o7fmtNPEpbVaQ2h1o6zDt7uoz+PX1L/guq7AtKGj?=
Message-ID: <alpha>

Something else.
""")
        with transaction():
            held_id = hold_message(self._mlist, self._msg)
        json, response = call_api(
            'http://*****:*****@example.com/held')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(json['total_size'], 1)
        self.assertEqual(json['entries'][0]['request_id'], held_id)
Exemple #41
0
 def test_existing_address_absorb(self):
     # Trying to add an existing address causes a merge if the
     # 'absorb_existing' flag is present.
     user_manager = getUtility(IUserManager)
     with transaction():
         anne = user_manager.create_user('*****@*****.**')
         user_manager.create_user('*****@*****.**')
     json, response = call_api(
         'http://*****:*****@example.com/addresses', {
             'email': '*****@*****.**',
             'absorb_existing': True,
         })
     self.assertIn('*****@*****.**',
                   [address.email for address in anne.addresses])
     self.assertEqual(response.status_code, 201)
     self.assertEqual(
         response.headers['location'],
         'http://*****:*****@example.com')
Exemple #42
0
    def test_mailing_list_with_different_address_and_list_id(self):
        # A mailing list can be renamed, in which case the list_name
        # will be different but the list_id will remain the same.
        # https://gitlab.com/mailman/mailman/issues/428
        with transaction():
            self._mlist.list_name = 'renamed'
        self.assertEqual(self._mlist.posting_address, '*****@*****.**')
        self._lmtp.sendmail(
            '*****@*****.**', ['*****@*****.**'], """\
From: [email protected]
To: [email protected]
Message-ID: <ant>
Subject: This should be accepted.

""")
        # The message is in the incoming queue but not the command queue.
        items = get_queue_messages('in', expected_count=1)
        self.assertEqual(items[0].msgdata['listid'], 'test.example.com')
Exemple #43
0
 def test_add_member_with_lower_case_email(self):
     # LP: #1425359 - Mailman is case-perserving, case-insensitive.  This
     # test subscribes the mixed case address and ensures the lower cased
     # address can't be added.
     with transaction():
         anne = self._usermanager.create_address('*****@*****.**')
         self._mlist.subscribe(anne)
     with self.assertRaises(HTTPError) as cm:
         call_api(
             'http://*****:*****@example.com',
                 'pre_verified': True,
                 'pre_confirmed': True,
                 'pre_approved': True,
             })
     self.assertEqual(cm.exception.code, 409)
     self.assertEqual(cm.exception.reason, 'Member already subscribed')
Exemple #44
0
 def test_create_new_membership_by_hex(self):
     with transaction():
         user = getUtility(IUserManager).create_user('*****@*****.**')
         set_preferred(user)
     # Subscribe the user to the mailing list by hex UUID.
     json, response = call_api(
         'http://localhost:9001/3.1/members', {
             'list_id': 'ant.example.com',
             'subscriber': '00000000000000000000000000000001',
             'pre_verified': True,
             'pre_confirmed': True,
             'pre_approved': True,
         })
     self.assertEqual(response.status_code, 201)
     self.assertEqual(
         response.headers['location'],
         'http://localhost:9001/3.1/members/00000000000000000000000000000001'
     )
Exemple #45
0
 def test_get_a_url(self):
     with transaction():
         getUtility(ITemplateManager).set('list:user:notice:welcome',
                                          'example.com',
                                          'http://example.com/welcome')
     resource, response = call_api(
         'http://localhost:9001/3.1/domains/example.com/uris'
         '/list:user:notice:welcome')
     self.assertEqual(response.status_code, 200)
     self.assertEqual(
         resource, {
             'http_etag':
             '"8884a0b3d675b4cb9899a7825daac9db88b70bed"',
             'self_link': ('http://localhost:9001/3.1/domains/example.com'
                           '/uris/list:user:notice:welcome'),
             'uri':
             'http://example.com/welcome',
         })
Exemple #46
0
 def test_user_subresource(self):
     # For an address which is linked to a user, accessing the user
     # subresource of the address path returns the user JSON representation.
     user_manager = getUtility(IUserManager)
     with transaction():
         user_manager.create_user('*****@*****.**', 'Anne')
     json, response = call_api(
         'http://*****:*****@example.com/user')
     self.assertEqual(response.status_code, 200)
     self.assertEqual(json['user_id'], 1)
     self.assertEqual(json['display_name'], 'Anne')
     user_resource = json['self_link']
     self.assertEqual(user_resource, 'http://localhost:9001/3.0/users/1')
     # The self_link points to the correct user.
     json, response = call_api(user_resource)
     self.assertEqual(json['user_id'], 1)
     self.assertEqual(json['display_name'], 'Anne')
     self.assertEqual(json['self_link'], user_resource)
 def _subscribe_and_add_bounce_event(self,
                                     addr,
                                     subscribe=True,
                                     create=True,
                                     context=None):
     user_mgr = getUtility(IUserManager)
     with transaction():
         if create:
             anne = user_mgr.create_address(addr)
         else:
             anne = user_mgr.get_address(addr)
         if subscribe:
             self._mlist.subscribe(anne)
         self._processor.register(self._mlist,
                                  addr,
                                  self._msg,
                                  where=context)
     return self._mlist.members.get_member(addr)
Exemple #48
0
 def test_get_all_users(self):
     user_manager = getUtility(IUserManager)
     with transaction():
         user_manager.create_user('*****@*****.**')
         user_manager.create_user('*****@*****.**')
     content, response = call_api('http://localhost:9001/3.1/users')
     entries = content['entries']
     self.assertEqual(len(entries), 2)
     self.assertEqual(entries[0]['user_id'],
                      '00000000000000000000000000000001')
     self.assertEqual(
         entries[0]['self_link'],
         'http://localhost:9001/3.1/users/00000000000000000000000000000001')
     self.assertEqual(entries[1]['user_id'],
                      '00000000000000000000000000000002')
     self.assertEqual(
         entries[1]['self_link'],
         'http://localhost:9001/3.1/users/00000000000000000000000000000002')
Exemple #49
0
 def test_existing_address_link_with_arguments(self):
     # Creating a user with an existing address links them, and the
     # addition arguments get honored.
     user_manager = getUtility(IUserManager)
     with transaction():
         user_manager.create_address('*****@*****.**')
     call_api('http://*****:*****@example.com',
         display_name='Anne Person',
         password='******',
         is_server_owner=True,
         ))
     anne = user_manager.get_user('*****@*****.**')
     self.assertEqual(anne.display_name, 'Anne Person')
     self.assertTrue(anne.is_server_owner)
     self.assertEqual(anne.password, '{plaintext}123')
     self.assertIn('*****@*****.**',
                   [address.email for address in anne.addresses])
Exemple #50
0
def subscribe(mlist, first_name, role=MemberRole.member):
    """Helper for subscribing a sample person to a mailing list."""
    user_manager = getUtility(IUserManager)
    email = '{0}[email protected]'.format(first_name[0].lower())
    full_name = '{0} Person'.format(first_name)
    with transaction():
        person = user_manager.get_user(email)
        if person is None:
            address = user_manager.get_address(email)
            if address is None:
                person = user_manager.create_user(email, full_name)
                preferred_address = list(person.addresses)[0]
                mlist.subscribe(preferred_address, role)
            else:
                mlist.subscribe(address, role)
        else:
            preferred_address = list(person.addresses)[0]
            mlist.subscribe(preferred_address, role)
Exemple #51
0
 def test_cannot_create_new_membership_by_int(self):
     with transaction():
         user = getUtility(IUserManager).create_user('*****@*****.**')
         set_preferred(user)
     # We can't use the int representation of the UUID with API 3.1.
     with self.assertRaises(HTTPError) as cm:
         call_api(
             'http://localhost:9001/3.1/members', {
                 'list_id': 'ant.example.com',
                 'subscriber': '1',
                 'pre_verified': True,
                 'pre_confirmed': True,
                 'pre_approved': True,
             })
     # This is a bad request because the `subscriber` value isn't something
     # that's known to the system, in API 3.1.  It's not technically a 404
     # because that's reserved for URL lookups.
     self.assertEqual(cm.exception.code, 400)
 def test_get_member_id_by_hex(self):
     with transaction():
         subscribe(self._mlist, 'Anne')
     response, headers = call_api(
         'http://*****:*****@example.com')
Exemple #53
0
 def test_get_list_member_id_by_email(self):
     with transaction():
         subscribe(self._mlist, 'Anne', email="*****@*****.**")
     json, response = call_api(
         'http://*****:*****@example.com')
     self.assertEqual(
         json['member_id'],
         '00000000000000000000000000000001')
     self.assertEqual(
       json['self_link'],
       'http://*****:*****@example.com')
Exemple #54
0
 def test_get_all_uris(self):
     manager = getUtility(ITemplateManager)
     with transaction():
         manager.set('list:user:notice:welcome', 'ant.example.com',
                     'http://example.com/welcome')
         manager.set(
             'list:user:notice:goodbye',
             'ant.example.com',
             'http://example.com/goodbye',
             'a user',
             'the password',
         )
     json, response = call_api(
         'http://localhost:9001/3.1/lists/ant.example.com/uris')
     self.assertEqual(response.status_code, 200)
     self.assertEqual(json['start'], 0)
     self.assertEqual(json['total_size'], 2)
     self.assertEqual(
         json['self_link'],
         'http://localhost:9001/3.1/lists/ant.example.com/uris')
     self.assertEqual(json['entries'], [{
         'http_etag':
         '"6612187ed6604ce54a57405fd66742557391ed4a"',
         'name':
         'list:user:notice:goodbye',
         'password':
         '******',
         'self_link': ('http://localhost:9001/3.1/lists/ant.example.com'
                       '/uris/list:user:notice:goodbye'),
         'uri':
         'http://example.com/goodbye',
         'username':
         '******',
     }, {
         'http_etag':
         '"cb1ab5eee2242143d2984edd0487532915ad3a8e"',
         'name':
         'list:user:notice:welcome',
         'self_link': ('http://localhost:9001/3.1/lists/ant.example.com'
                       '/uris/list:user:notice:welcome'),
         'uri':
         'http://example.com/welcome',
     }])
Exemple #55
0
 def test_delete_all_uris(self):
     manager = getUtility(ITemplateManager)
     with transaction():
         manager.set(
             'list:user:notice:welcome', 'ant.example.com',
             'http://example.com/welcome')
         manager.set(
             'list:user:notice:goodbye', 'ant.example.com',
             'http://example.com/goodbye',
             'a user', 'the password',
             )
     json, response = call_api(
         'http://localhost:9001/3.1/lists/ant.example.com/uris',
         method='DELETE')
     self.assertEqual(response.status_code, 204)
     self.assertIsNone(
         manager.raw('list:user:notice:welcome', 'ant.example.com'))
     self.assertIsNone(
         manager.raw('list:user:notice:goodbye', 'ant.example.com'))
Exemple #56
0
 def _dispose(self, mlist, msg, msgdata):
     """See `IRunner`."""
     if msgdata.get('envsender') is None:
         msgdata['envsender'] = mlist.no_reply_address
     # Ensure that the email addresses of the message's senders are known
     # to Mailman.  This will be used in nonmember posting dispositions.
     user_manager = getUtility(IUserManager)
     with transaction():
         for sender in msg.senders:
             try:
                 user_manager.create_address(sender)
             except ExistingAddressError:
                 pass
     # Process the message through the mailing list's start chain.
     start_chain = (mlist.owner_chain if msgdata.get('to_owner', False) else
                    mlist.posting_chain)
     process(mlist, msg, msgdata, start_chain)
     # Do not keep this message queued.
     return False
 def test_patch_bad_regexp(self):
     header_matches = IHeaderMatchList(self._mlist)
     with transaction():
         header_matches.append('header', 'pattern')
     with self.assertRaises(HTTPError) as cm:
         call_api(
             'http://localhost:9001/3.0/lists/ant.example.com'
             '/header-matches/0', {
                 'header': 'header',
                 'pattern': '+invalid',
             },
             method='PATCH')
     self.assertEqual(cm.exception.code, 400)
     self.assertEqual(
         cm.exception.reason, 'Invalid Parameter "pattern":'
         ' Expected a valid regexp, got +invalid.')
     self.assertEqual(
         cm.exception.reason, 'Invalid Parameter "pattern": '
         'Expected a valid regexp, got +invalid.')
Exemple #58
0
 def test_address_and_display_name_added_to_user(self):
     # Address with a display name is added to the user record.
     user_manager = getUtility(IUserManager)
     with transaction():
         anne = user_manager.create_user('*****@*****.**')
     response, content = call_api(
         'http://*****:*****@example.com/addresses', {
             'email': '*****@*****.**',
             'display_name': 'Ann E Person',
         })
     self.assertIn('*****@*****.**',
                   [addr.email for addr in anne.addresses])
     self.assertEqual(content['status'], '201')
     self.assertEqual(
         content['location'],
         'http://*****:*****@example.org')
     # The address has no display name.
     anne_person = user_manager.get_address('*****@*****.**')
     self.assertEqual(anne_person.display_name, 'Ann E Person')
Exemple #59
0
 def test_user_subresource_post_new_user(self):
     # If the address is not yet linked to a user, POSTing to the 'user'
     # subresources creates a new user object and links it to the address.
     user_manager = getUtility(IUserManager)
     with transaction():
         anne_addr = user_manager.create_address('*****@*****.**')
     response, headers = call_api(
         'http://*****:*****@example.com/user', {
             'display_name': 'Anne',
         })
     self.assertEqual(headers['status'], '201')
     anne = user_manager.get_user('*****@*****.**')
     self.assertIsNotNone(anne)
     self.assertEqual(anne.display_name, 'Anne')
     self.assertEqual([a.email for a in anne.addresses],
                      ['*****@*****.**'])
     self.assertEqual(anne_addr.user, anne)
     self.assertEqual(headers['location'],
                      'http://localhost:9001/3.0/users/1')
Exemple #60
0
 def test_add_unlinked_address_to_user(self):
     user_manager = getUtility(IUserManager)
     with transaction():
         anne = user_manager.create_user('*****@*****.**')
         user_manager.create_address('*****@*****.**')
     response, content = call_api(
         'http://*****:*****@example.com/addresses',
         {
             'email': '*****@*****.**',
         })
     self.assertIn('*****@*****.**',
                   [address.email for address in anne.addresses])
     self.assertEqual(content['status'], '201')
     self.assertEqual(
         content['location'],
         'http://*****:*****@example.com')
     # The address has no display name.
     anne_person = user_manager.get_address('*****@*****.**')
     self.assertEqual(anne_person.display_name, '')