From b4eaeead13e21c09f33f92d2f5edd255c593cdbd Mon Sep 17 00:00:00 2001 From: Martin Hauser Date: Mon, 15 Sep 2025 20:36:51 +0200 Subject: [PATCH] Fixes #20342: Override create_superuser to drop is_staff (#20351) * fix(users): Override create_superuser to drop is_staff Override `UserManager.create_superuser()` to strip `is_staff` from `extra_fields` and enforce `is_superuser=True`, fixing the `TypeError` during `createsuperuser` with the custom `User` model. Fixes #20342 * Set alters_data=True on manager methods --------- Co-authored-by: Jeremy Stretch --- netbox/users/models/users.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/netbox/users/models/users.py b/netbox/users/models/users.py index 4a7e917b33..cbfb463300 100644 --- a/netbox/users/models/users.py +++ b/netbox/users/models/users.py @@ -3,7 +3,7 @@ from django.contrib.auth.models import ( GroupManager as DjangoGroupManager, Permission, PermissionsMixin, - UserManager as DjangoUserManager + UserManager as DjangoUserManager, ) from django.contrib.auth.validators import UnicodeUsernameValidator from django.core.exceptions import ValidationError @@ -74,9 +74,37 @@ class Group(models.Model): class UserManager(DjangoUserManager.from_queryset(RestrictedQuerySet)): def create_user(self, username, email=None, password=None, **extra_fields): - extra_fields.setdefault("is_superuser", False) + extra_fields.setdefault('is_superuser', False) return self._create_user(username, email, password, **extra_fields) + create_user.alters_data = True + + async def acreate_user(self, username, email=None, password=None, **extra_fields): + extra_fields.setdefault('is_superuser', False) + return await self._acreate_user(username, email, password, **extra_fields) + + acreate_user.alters_data = True + + def create_superuser(self, username, email=None, password=None, **extra_fields): + extra_fields.setdefault('is_superuser', True) + + if extra_fields.get('is_superuser') is not True: + raise ValueError('Superuser must have is_superuser=True.') + + return self._create_user(username, email, password, **extra_fields) + + create_superuser.alters_data = True + + async def acreate_superuser(self, username, email=None, password=None, **extra_fields): + extra_fields.setdefault('is_superuser', True) + + if extra_fields.get('is_superuser') is not True: + raise ValueError('Superuser must have is_superuser=True.') + + return await self._acreate_user(username, email, password, **extra_fields) + + acreate_superuser.alters_data = True + class User(AbstractBaseUser, PermissionsMixin): username = models.CharField(