diff --git a/flags/conditions/validators.py b/flags/conditions/validators.py index c85e14a..80d35d5 100644 --- a/flags/conditions/validators.py +++ b/flags/conditions/validators.py @@ -3,6 +3,7 @@ from django.contrib.auth import get_user_model from django.core.exceptions import ValidationError from django.core.validators import RegexValidator +from django.db import OperationalError, ProgrammingError from django.utils import dateparse from flags.utils import strtobool @@ -45,6 +46,13 @@ def validate_user(value): UserModel.objects.get(**{UserModel.USERNAME_FIELD: value}) except UserModel.DoesNotExist as err: raise ValidationError("Enter the username of a valid user.") from err + except (OperationalError, ProgrammingError): + # The user table may not exist yet, for example when the system checks + # run during a migration against a fresh database (before the auth + # tables are created). The username cannot be checked in that case, so + # skip validation rather than letting the database error abort the + # migration. + pass def validate_date(value): diff --git a/flags/tests/test_conditions_validators.py b/flags/tests/test_conditions_validators.py index ed9c782..d389bbc 100644 --- a/flags/tests/test_conditions_validators.py +++ b/flags/tests/test_conditions_validators.py @@ -1,5 +1,8 @@ +from unittest import mock + from django.contrib.auth import get_user_model from django.core.exceptions import ValidationError +from django.db import OperationalError, ProgrammingError from django.test import TestCase, override_settings from flags.conditions.validators import ( @@ -82,6 +85,19 @@ def test_custom_user_invalid(self): with self.assertRaises(ValidationError): validate_user("nottestuser") + def test_user_table_missing_is_skipped(self): + # If the user table does not exist yet (for example when the system + # checks run during a migration against a fresh database), the lookup + # raises a database error. Validation should be skipped rather than + # letting that error abort the migration. See GH-96. + User = get_user_model() + for exc in (OperationalError, ProgrammingError): + with mock.patch.object( + User.objects, "get", side_effect=exc("relation does not exist") + ): + # Must not raise. + validate_user("testuser") + class ValidateDateTestCase(TestCase): def test_invalid_date_strings(self):