Django admin → Users: adding a person saves an empty username, and the second one fails with a 500 #427
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#427
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo at
95348908d, reading the admin registration and running its add form against the test database.Related to #1.
Checked again on 2026-10-01 against
mainat0a5cad587: still present. The signup rule the fix points to is now ataccounts/forms.py:908-913;accounts/admin.pyand the cited lines ofaccounts/models.pyhave not moved.UserAdminreplaces Django'sfieldsetsandadd_fieldsetswith lists that leave outusername, althoughUser.USERNAME_FIELDisusernameand the field is unique and obligatory. The admin builds its add form fromadd_fieldsets, so the username is never asked for, the model validation skips the excluded field, andUser.savestores''. The first person added this way has no username; the second cannot be added at all.accounts/admin.py:14-29,UserAdmin.fieldsets,UserAdmin.add_fieldsets,list_displayandsearch_fields;accounts/models.py:130-133,User.save.POSTULO_ADMIN_URLset),admin.site._registry[User].get_form(request)has the fieldsemail,password1,password2andusable_password. Saving it fora@example.orggives a user whoseusernameis''; saving it again forb@example.orgraisesIntegrityError: UNIQUE constraint failed: accounts_user.username, which the admin answers with a 500. The change form has nousernameeither (email,password,first_name,last_name, the permissions and the dates), so the empty username cannot be corrected there, and the list neither shows nor searches it.User's docstring that a username and a full name are both obligatory,User.__str__returns''wherever the account is named, and the path an operator is most likely to try in the admin ends in a server error.UserManager.create_useralready derives a username from the address when none is given (accounts/models.py:61-66), but the admin form bypasses the manager.usernamein bothadd_fieldsetsandfieldsets(andfirst_name,last_nameinadd_fieldsets, since a full name is obligatory too), add it tolist_displayandsearch_fields, and give the admin's add and change forms aclean_usernamethat applies the same rules as signup,get_adapter().clean_username(...)asaccounts/forms.py:911-916does, so the blacklist holds there too. Alternatively, when the field is left blank, derive it withslug_from_emailandunique_usernameas the manager does.Done when
tests/security/test_admin_exposure.py(which already mounts the admin with itswith_an_adminfixture) adds two people through the admin's add form and finds both saved with non-empty, distinct usernames, and a blacklisted username refused.