[Mailman-Developers] REST API delete user function does not delete every 2nd linked address

Andrew Stuart andrew.stuart at supercoders.com.au
Sun Feb 8 21:06:07 CET 2015


This appears to fix the problme in rest/users.py

    def on_delete(self, request, response):
        """Delete the named user, all her memberships, and addresses."""
        if self._user is None:
            not_found(response)
            return
        for member in self._user.memberships.members:
            member.unsubscribe()
        user_manager = getUtility(IUserManager)
        addresses_for_deletion = []
        for address in self._user.addresses:
            # to avoid mutating the self._user.addresses iterator, create a separate list of addresses
            addresses_for_deletion.append(address)
        for address in addresses_for_deletion:
            user_manager.delete_address(address)
        user_manager.delete_user(self._user)
        no_content(response)


On 8 Feb 2015, at 11:07 pm, Andrew Stuart <andrew.stuart at supercoders.com.au> wrote:

I might need some help to track this down……..

When a user is deleted via the REST API, there is a function that appears to be iterating over the users addresses and unlinking them.

Is it possible that the unlinking process is somehow mutating the list of addresses that calling function is using? So as each address is unlinked somehow the underlying list of addresses is no longer able to be used as an effective address iterator?

Here are the relevant functions:

in rest/users.py (this is call from the REST API)

   def on_delete(self, request, response):
       """Delete the named user, all her memberships, and addresses."""
       if self._user is None:
           not_found(response)
           return
       for member in self._user.memberships.members:
           member.unsubscribe()
       user_manager = getUtility(IUserManager)
       for address in self._user.addresses:
           debug_log.info('address scheduled for deletion: {}'.format(address))
       for address in self._user.addresses:
           user_manager.delete_address(address)
       user_manager.delete_user(self._user)
       no_content(response)

*********> the debug.log line above returns a full list of all the addresses scheduled for deletion, proving that all the expected addresses are present in self._user.addresses
*********> THE NEXT LINE "for address in self._user.addresses:” IS DOING THE SKIPPING.
*********>>> SO - COULD IT BE that self._user.addresses is being mutated by user_manager.delete_address(address), stuffing up the for loop that is meant to be iterating over all addresses? Which is to say, as each address is unlinked, the length of and values in self._user.addresses is changing?

in usermanager.py

   @dbconnection
   def delete_address(self, store, address):
       """See `IUserManager`."""
       # If there's a user controlling this address, it has to first be
       # unlinked before the address can be deleted.
       if address.user:
           address.user.unlink(address)
       store.delete(address)



_______________________________________________
Mailman-Developers mailing list
Mailman-Developers at python.org
https://mail.python.org/mailman/listinfo/mailman-developers
Mailman FAQ: http://wiki.list.org/x/AgA3
Searchable Archives: http://www.mail-archive.com/mailman-developers%40python.org/
Unsubscribe: https://mail.python.org/mailman/options/mailman-developers/andrew.stuart%40supercoders.com.au

Security Policy: http://wiki.list.org/x/QIA9



More information about the Mailman-Developers mailing list