1. from django.contrib.auth.models import (
    
  2.     AbstractBaseUser,
    
  3.     AbstractUser,
    
  4.     BaseUserManager,
    
  5.     Group,
    
  6.     Permission,
    
  7.     PermissionsMixin,
    
  8.     UserManager,
    
  9. )
    
  10. from django.db import models
    
  11. 
    
  12. 
    
  13. # The custom user uses email as the unique identifier, and requires
    
  14. # that every user provide a date of birth. This lets us test
    
  15. # changes in username datatype, and non-text required fields.
    
  16. class CustomUserManager(BaseUserManager):
    
  17.     def create_user(self, email, date_of_birth, password=None, **fields):
    
  18.         """
    
  19.         Creates and saves a User with the given email and password.
    
  20.         """
    
  21.         if not email:
    
  22.             raise ValueError("Users must have an email address")
    
  23. 
    
  24.         user = self.model(
    
  25.             email=self.normalize_email(email), date_of_birth=date_of_birth, **fields
    
  26.         )
    
  27. 
    
  28.         user.set_password(password)
    
  29.         user.save(using=self._db)
    
  30.         return user
    
  31. 
    
  32.     def create_superuser(self, email, password, date_of_birth, **fields):
    
  33.         u = self.create_user(
    
  34.             email, password=password, date_of_birth=date_of_birth, **fields
    
  35.         )
    
  36.         u.is_admin = True
    
  37.         u.save(using=self._db)
    
  38.         return u
    
  39. 
    
  40. 
    
  41. class CustomUser(AbstractBaseUser):
    
  42.     email = models.EmailField(verbose_name="email address", max_length=255, unique=True)
    
  43.     is_active = models.BooleanField(default=True)
    
  44.     is_admin = models.BooleanField(default=False)
    
  45.     date_of_birth = models.DateField()
    
  46.     first_name = models.CharField(max_length=50)
    
  47. 
    
  48.     custom_objects = CustomUserManager()
    
  49. 
    
  50.     USERNAME_FIELD = "email"
    
  51.     REQUIRED_FIELDS = ["date_of_birth", "first_name"]
    
  52. 
    
  53.     def __str__(self):
    
  54.         return self.email
    
  55. 
    
  56.     # Maybe required?
    
  57.     def get_group_permissions(self, obj=None):
    
  58.         return set()
    
  59. 
    
  60.     def get_all_permissions(self, obj=None):
    
  61.         return set()
    
  62. 
    
  63.     def has_perm(self, perm, obj=None):
    
  64.         return True
    
  65. 
    
  66.     def has_perms(self, perm_list, obj=None):
    
  67.         return True
    
  68. 
    
  69.     def has_module_perms(self, app_label):
    
  70.         return True
    
  71. 
    
  72.     # Admin required fields
    
  73.     @property
    
  74.     def is_staff(self):
    
  75.         return self.is_admin
    
  76. 
    
  77. 
    
  78. class RemoveGroupsAndPermissions:
    
  79.     """
    
  80.     A context manager to temporarily remove the groups and user_permissions M2M
    
  81.     fields from the AbstractUser class, so they don't clash with the
    
  82.     related_name sets.
    
  83.     """
    
  84. 
    
  85.     def __enter__(self):
    
  86.         self._old_au_local_m2m = AbstractUser._meta.local_many_to_many
    
  87.         self._old_pm_local_m2m = PermissionsMixin._meta.local_many_to_many
    
  88.         groups = models.ManyToManyField(Group, blank=True)
    
  89.         groups.contribute_to_class(PermissionsMixin, "groups")
    
  90.         user_permissions = models.ManyToManyField(Permission, blank=True)
    
  91.         user_permissions.contribute_to_class(PermissionsMixin, "user_permissions")
    
  92.         PermissionsMixin._meta.local_many_to_many = [groups, user_permissions]
    
  93.         AbstractUser._meta.local_many_to_many = [groups, user_permissions]
    
  94. 
    
  95.     def __exit__(self, exc_type, exc_value, traceback):
    
  96.         AbstractUser._meta.local_many_to_many = self._old_au_local_m2m
    
  97.         PermissionsMixin._meta.local_many_to_many = self._old_pm_local_m2m
    
  98. 
    
  99. 
    
  100. class CustomUserWithoutIsActiveField(AbstractBaseUser):
    
  101.     username = models.CharField(max_length=150, unique=True)
    
  102.     email = models.EmailField(unique=True)
    
  103. 
    
  104.     objects = UserManager()
    
  105. 
    
  106.     USERNAME_FIELD = "username"
    
  107. 
    
  108. 
    
  109. # The extension user is a simple extension of the built-in user class,
    
  110. # adding a required date_of_birth field. This allows us to check for
    
  111. # any hard references to the name "User" in forms/handlers etc.
    
  112. with RemoveGroupsAndPermissions():
    
  113. 
    
  114.     class ExtensionUser(AbstractUser):
    
  115.         date_of_birth = models.DateField()
    
  116. 
    
  117.         custom_objects = UserManager()
    
  118. 
    
  119.         REQUIRED_FIELDS = AbstractUser.REQUIRED_FIELDS + ["date_of_birth"]