Fix issue where we didn't delete robots immediately under a namespace

This could result in "hanging" robot accounts, although that would only leak the names of said accounts. Now we delete them immediately AND we proactively delete them before replacing the namespace (just to be sure)
This commit is contained in:
Joseph Schorr 2018-05-09 14:52:28 +03:00
parent bd1f3e6bb8
commit f06eec8a35
5 changed files with 132 additions and 10 deletions

View file

@ -0,0 +1,28 @@
from data.database import User
from util.names import parse_robot_username
def cleanup_old_robots(page_size=50):
""" Deletes any robots that live under namespaces that no longer exist. """
# Collect the robot accounts to delete.
page_number = 1
to_delete = []
while True:
found_bots = False
for robot in list(User.select().where(User.robot == True).paginate(page_number, page_size)):
found_bots = True
namespace, _ = parse_robot_username(robot.username)
try:
User.get(username=namespace)
except User.DoesNotExist:
# Save the robot account for deletion.
to_delete.append(robot)
if not found_bots:
break
page_number = page_number + 1
# Cleanup any robot accounts whose corresponding namespace doesn't exist.
for robot in to_delete:
robot.delete_instance(recursive=True, delete_nullable=True)

View file

@ -0,0 +1,43 @@
import pytest
from data.database import User
from util.migrate.cleanup_old_robots import cleanup_old_robots
from test.fixtures import *
def test_cleanup_old_robots(initialized_db):
before_robot_count = User.select().where(User.robot == True).count()
before_user_count = User.select().count()
# Run the cleanup once, and ensure it does nothing.
cleanup_old_robots()
after_robot_count = User.select().where(User.robot == True).count()
after_user_count = User.select().count()
assert before_robot_count == after_robot_count
assert before_user_count == after_user_count
# Create some orphan robots.
created = set()
for index in range(0, 50):
created.add('doesnotexist+a%s' % index)
created.add('anothernamespace+b%s' % index)
User.create(username='doesnotexist+a%s' % index, robot=True)
User.create(username='anothernamespace+b%s' % index, robot=True)
before_robot_count = User.select().where(User.robot == True).count()
before_user_count = User.select().count()
cleanup_old_robots(page_size=10)
after_robot_count = User.select().where(User.robot == True).count()
after_user_count = User.select().count()
assert before_robot_count == after_robot_count + len(created)
assert before_user_count == after_user_count + len(created)
for name in created:
with pytest.raises(User.DoesNotExist):
User.get(username=name)