Define a model manager for User model with no username field.
| 72 | |
| 73 | |
| 74 | class UserManager(BaseUserManager): # type: ignore[type-arg] |
| 75 | """Define a model manager for User model with no username field.""" |
| 76 | |
| 77 | use_in_migrations = True |
| 78 | |
| 79 | def _create_user(self, email, password, **extra_fields): # type: ignore[no-untyped-def] |
| 80 | """Create and save a User with the given email and password.""" |
| 81 | if not email: |
| 82 | raise ValueError("The given email must be set") |
| 83 | email = self.normalize_email(email) |
| 84 | user = self.model(email=email, **extra_fields) |
| 85 | user.set_password(password) |
| 86 | user.save(using=self._db) |
| 87 | return user |
| 88 | |
| 89 | def create_user(self, email, password=None, **extra_fields): # type: ignore[no-untyped-def] |
| 90 | """Create and save a regular User with the given email and password.""" |
| 91 | extra_fields.setdefault("is_staff", False) |
| 92 | extra_fields.setdefault("is_superuser", False) |
| 93 | return self._create_user(email, password, **extra_fields) # type: ignore[no-untyped-call] |
| 94 | |
| 95 | def create_superuser(self, email, password, **extra_fields): # type: ignore[no-untyped-def] |
| 96 | """Create and save a SuperUser with the given email and password.""" |
| 97 | extra_fields.setdefault("is_staff", True) |
| 98 | extra_fields.setdefault("is_superuser", True) |
| 99 | |
| 100 | if extra_fields.get("is_staff") is not True: |
| 101 | raise ValueError("Superuser must have is_staff=True.") |
| 102 | if extra_fields.get("is_superuser") is not True: |
| 103 | raise ValueError("Superuser must have is_superuser=True.") |
| 104 | |
| 105 | return self._create_user(email, password, **extra_fields) # type: ignore[no-untyped-call] |
| 106 | |
| 107 | def get_by_natural_key(self, email): # type: ignore[no-untyped-def] |
| 108 | # Used to allow case insensitive login |
| 109 | return self.get(email__iexact=email) |
| 110 | |
| 111 | def make_random_password( |
| 112 | self, |
| 113 | length: int = 10, |
| 114 | allowed_chars: str = string.ascii_letters + string.digits, |
| 115 | ) -> str: |
| 116 | return "".join(secrets.choice(allowed_chars) for _ in range(length)) |
| 117 | |
| 118 | |
| 119 | class FFAdminUser(LifecycleModel, AbstractUser): # type: ignore[django-manager-missing,misc] |