models.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. from urllib import parse
  2. from django.db import models
  3. from django.contrib.auth.models import (
  4. BaseUserManager,
  5. AbstractBaseUser,
  6. PermissionsMixin,
  7. )
  8. from django.utils.translation import gettext_lazy as _
  9. class UserManager(BaseUserManager):
  10. """
  11. A custom user manager to deal with emails as unique identifiers for auth
  12. instead of usernames. The default that's used is "UserManager"
  13. """
  14. def create_user(self, email, password, **extra_fields):
  15. """
  16. Creates and saves a User with the given email and password.
  17. """
  18. if not email:
  19. raise ValueError("The Email must be set")
  20. email = self.normalize_email(email)
  21. user = self.model(email=email, **extra_fields)
  22. user.set_password(password)
  23. user.save()
  24. return user
  25. def create_superuser(self, email, password, **extra_fields):
  26. extra_fields.setdefault("is_staff", True)
  27. extra_fields.setdefault("is_superuser", True)
  28. extra_fields.setdefault("is_active", True)
  29. if extra_fields.get("is_staff") is not True:
  30. raise ValueError("Superuser must have is_staff=True.")
  31. if extra_fields.get("is_superuser") is not True:
  32. raise ValueError("Superuser must have is_superuser=True.")
  33. return self.create_user(email, password, **extra_fields)
  34. class User(AbstractBaseUser, PermissionsMixin):
  35. email = models.EmailField(unique=True)
  36. name = models.CharField(_("name"), max_length=255, blank=True)
  37. is_staff = models.BooleanField(
  38. _("staff status"),
  39. default=False,
  40. help_text=_("Designates whether the user can log into this site."),
  41. )
  42. is_active = models.BooleanField(
  43. _("active"),
  44. default=True,
  45. help_text=_(
  46. "Designates whether this user should be treated as active. "
  47. "Unselect this instead of deleting accounts."
  48. ),
  49. )
  50. analytics = models.JSONField(null=True, blank=True)
  51. created = models.DateTimeField(auto_now_add=True)
  52. subscribe_by_default = models.BooleanField(
  53. default=True,
  54. help_text="Subscribe to project notifications by default. Overrides project settings",
  55. )
  56. USERNAME_FIELD = "email"
  57. EMAIL_FIELD = "email"
  58. objects = UserManager()
  59. def __str__(self):
  60. return self.email
  61. def get_full_name(self):
  62. return self.email
  63. def get_short_name(self):
  64. return self.email
  65. @property
  66. def username(self):
  67. return self.email
  68. @property
  69. def auth_token(self):
  70. return None
  71. def set_register_analytics_tags(self, tags: str):
  72. """
  73. Set UTM querystring to user's analytics field
  74. """
  75. parsed_tags = parse.parse_qsl(tags.strip("?"))
  76. if self.analytics is None:
  77. self.analytics = {}
  78. self.analytics["register"] = {
  79. tag[0]: tag[1] for tag in parsed_tags if tag[0].startswith("utm_")
  80. }
  81. class ProjectAlertStatus(models.IntegerChoices):
  82. OFF = 0, "off"
  83. ON = 1, "on"
  84. class UserProjectAlert(models.Model):
  85. """
  86. Determine if user alert notifications should always happen, never, or defer to default
  87. Default is stored as the lack of record.
  88. """
  89. user = models.ForeignKey(User, on_delete=models.CASCADE)
  90. project = models.ForeignKey("projects.Project", on_delete=models.CASCADE)
  91. status = models.PositiveSmallIntegerField(choices=ProjectAlertStatus.choices)
  92. class Meta:
  93. unique_together = ("user", "project")