REST API delete user function does not delete every 2nd linked address

Bug #1419519 reported by Andrew Stuart
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
GNU Mailman
Fix Released
High
Barry Warsaw

Bug Description

The following series of curl commands creates a user with an email address of ‘<email address hidden>’, and then links 10 additional addresses to <email address hidden>

curl -X POST --data "<email address hidden>&display_name=z" --header "authorization: Basic cmVzdGFkbWluOnJlc3RwYXNz" http://localhost:8001/3.0/users
curl -X POST --data "<email address hidden>" --header "authorization: Basic cmVzdGFkbWluOnJlc3RwYXNz" http://localhost:<email address hidden>/addresses
curl -X POST --data "<email address hidden>" --header "authorization: Basic cmVzdGFkbWluOnJlc3RwYXNz" http://localhost:<email address hidden>/addresses
curl -X POST --data "<email address hidden>" --header "authorization: Basic cmVzdGFkbWluOnJlc3RwYXNz" http://localhost:<email address hidden>/addresses
curl -X POST --data "<email address hidden>" --header "authorization: Basic cmVzdGFkbWluOnJlc3RwYXNz" http://localhost:<email address hidden>/addresses
curl -X POST --data "<email address hidden>" --header "authorization: Basic cmVzdGFkbWluOnJlc3RwYXNz" http://localhost:<email address hidden>/addresses
curl -X POST --data "<email address hidden>" --header "authorization: Basic cmVzdGFkbWluOnJlc3RwYXNz" http://localhost:<email address hidden>/addresses
curl -X POST --data "<email address hidden>" --header "authorization: Basic cmVzdGFkbWluOnJlc3RwYXNz" http://localhost:<email address hidden>/addresses
curl -X POST --data "<email address hidden>" --header "authorization: Basic cmVzdGFkbWluOnJlc3RwYXNz" http://localhost:<email address hidden>/addresses
curl -X POST --data "<email address hidden>" --header "authorization: Basic cmVzdGFkbWluOnJlc3RwYXNz" http://localhost:<email address hidden>/addresses
curl -X POST --data "<email address hidden>" --header "authorization: Basic cmVzdGFkbWluOnJlc3RwYXNz" http://localhost:<email address hidden>/addresses

A sqlite3 dump of the database shows the following in the addresses table:

INSERT INTO "address" VALUES(11,'<email address hidden>',NULL,'z',NULL,'2015-02-08 10:50:37.241724',5,17);
INSERT INTO "address" VALUES(12,'<email address hidden>',NULL,'',NULL,'2015-02-08 10:52:08.928901',5,19);
INSERT INTO "address" VALUES(13,'<email address hidden>',NULL,'',NULL,'2015-02-08 10:52:36.308978',5,20);
INSERT INTO "address" VALUES(14,'<email address hidden>',NULL,'',NULL,'2015-02-08 10:52:43.947229',5,21);
INSERT INTO "address" VALUES(15,'<email address hidden>',NULL,'',NULL,'2015-02-08 10:52:49.598934',5,22);
INSERT INTO "address" VALUES(16,'<email address hidden>',NULL,'',NULL,'2015-02-08 10:52:54.406450',5,23);
INSERT INTO "address" VALUES(17,'<email address hidden>',NULL,'',NULL,'2015-02-08 10:52:59.295078',5,24);
INSERT INTO "address" VALUES(18,'<email address hidden>',NULL,'',NULL,'2015-02-08 10:53:04.892381',5,25);
INSERT INTO "address" VALUES(19,'<email address hidden>',NULL,'',NULL,'2015-02-08 10:53:10.497119',5,26);
INSERT INTO "address" VALUES(20,'<email address hidden>',NULL,'',NULL,'2015-02-08 10:53:16.450507',5,27);
INSERT INTO "address" VALUES(21,'<email address hidden>',NULL,'',NULL,'2015-02-08 10:53:24.021368',5,28);

All good at this stage. No problems.

The following curl command deletes user ‘<email address hidden>’

curl --verbose -X DELETE --header "authorization: Basic cmVzdGFkbWluOnJlc3RwYXNz" http://localhost:<email address hidden>

Strangely, a sqlite3 dump of the database now shows the following in the addresses table:

INSERT INTO "address" VALUES(12,'<email address hidden>',NULL,'',NULL,'2015-02-08 10:52:08.928901',NULL,19);
INSERT INTO "address" VALUES(14,'<email address hidden>',NULL,'',NULL,'2015-02-08 10:52:43.947229',NULL,21);
INSERT INTO "address" VALUES(16,'<email address hidden>',NULL,'',NULL,'2015-02-08 10:52:54.406450',NULL,23);
INSERT INTO "address" VALUES(18,'<email address hidden>',NULL,'',NULL,'2015-02-08 10:53:04.892381',NULL,25);
INSERT INTO "address" VALUES(20,'<email address hidden>',NULL,'',NULL,'2015-02-08 10:53:16.450507',NULL,27);

So 6 of the addresses that should have been deleted were deleted, but 5 remain. The linked address deletion seems to be skipping addresses for some reason.

It appears the problem is caused by the delete address functionality mutating the iterator of user addresses.

This appears to fix the problem, which is 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)

Tags: mailman3
Barry Warsaw (barry)
tags: added: mailman3
Barry Warsaw (barry)
Changed in mailman:
milestone: none → 3.0.0b6
assignee: nobody → Barry Warsaw (barry)
importance: Undecided → High
status: New → In Progress
Barry Warsaw (barry)
Changed in mailman:
status: In Progress → Fix Committed
Barry Warsaw (barry)
Changed in mailman:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.