Skip to content

Commit 6b56ee3

Browse files
committed
Remove resurrected User.__init__ that mutated Field.validators
PR #1374 (50ed674) fixed #1358 by deleting the User.__init__ override that re-bound `username_field.validators[0] = UserUnicodeUsernameValidator()` on every instantiation. The merge commit b68c1cb (resolving issue #1333, the auth/users typing pass) carried the mypy-typed version of that same __init__ forward and the merge-in-main resurrected it on origin/main at 6d2cddb. The class-body declaration `validators=[UserUnicodeUsernameValidator()]` from PR #1374 is the canonical and only validator binding — the __init__ override was a shared-state mutation that clobbered anything third-party prepended to the field's validators list (and changed validator identity on each instantiation). The two regression tests that exposed this on main are already in the repo and pass with this change: - test_validators_list_stable_across_instantiations - test_third_party_prepend_does_not_corrupt_username_validator Also drop the now-unused `Field` import.
1 parent 6d2cddb commit 6b56ee3

2 files changed

Lines changed: 5 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
12+
- **`User.__init__` shared-state mutation re-introduced by branch merge** (`opencontractserver/users/models.py:172-180` removed): PR #1374 (commit `50ed6740`) deleted the `User.__init__` override that mutated `Field.validators[0]` on every instantiation, but a subsequent merge (`b68c1cb4 → 6d2cddbf`) resurrected the override along with its mypy-narrowing changes. The current main on commit `6d2cddbf` therefore reproduced the original `#1358` bug: `User(...)` rebound `username_field.validators[0]` and clobbered any third-party validator prepended to the list. Removed the `__init__` override entirely; the class-body declaration `validators=[UserUnicodeUsernameValidator()]` on the `username` field (still present from PR #1374) is the canonical and only declaration. Also dropped the now-unused `Field` import. Regression coverage from PR #1374 (`opencontractserver/tests/test_user_username_validator.py`) was already on main and is what surfaced the regression in CI.
13+
1014
### Security
1115

1216
- **Cross-corpus structural-annotation leak in `CoreAnnotationVectorStore`** (`opencontractserver/llms/vector_stores/core_vector_stores.py:296-326,371-413`): The corpus-wide retrieval path (`corpus_id` set, `document_id=None`) returned every structural annotation in the database regardless of corpus. Two collaborating defects caused the leak:

opencontractserver/users/models.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
Group,
1313
)
1414
from django.contrib.auth.models import UserManager as DjangoUserManager
15-
from django.db.models import Field, Q, QuerySet
15+
from django.db.models import Q, QuerySet
1616
from django.urls import reverse
1717
from django.utils import timezone
1818
from django.utils.translation import gettext_lazy as _
@@ -169,16 +169,6 @@ class User(AbstractUser):
169169
def __str__(self) -> str:
170170
return f"{self.username}: {self.email}"
171171

172-
def __init__(self, *args: Any, **kwargs: Any) -> None:
173-
username_field = self._meta.get_field("username")
174-
# ``get_field`` is typed as ``Field | ForeignObjectRel``; the
175-
# username field is always a plain ``Field``, but narrow here so
176-
# mypy can see ``.validators`` without a cast.
177-
if isinstance(username_field, Field):
178-
username_field.validators[0] = UserUnicodeUsernameValidator()
179-
180-
super().__init__(*args, **kwargs)
181-
182172
def get_absolute_url(self) -> str:
183173
"""Get url for user's detail view.
184174

0 commit comments

Comments
 (0)