models.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. from urllib import parse
  2. from django.contrib.auth.models import (
  3. AbstractBaseUser,
  4. BaseUserManager,
  5. PermissionsMixin,
  6. )
  7. from django.db import models
  8. from django.db.models import Q
  9. from django.utils.translation import gettext_lazy as _
  10. from apps.projects.models import ProjectAlertStatus
  11. class UserManager(BaseUserManager):
  12. """
  13. A custom user manager to deal with emails as unique identifiers for auth
  14. instead of usernames. The default that's used is "UserManager"
  15. """
  16. def create_user(self, email, password, **extra_fields):
  17. """
  18. Creates and saves a User with the given email and password.
  19. """
  20. if not email:
  21. raise ValueError("The Email must be set")
  22. email = self.normalize_email(email)
  23. user = self.model(email=email, **extra_fields)
  24. user.set_password(password)
  25. user.save()
  26. return user
  27. def create_superuser(self, email, password, **extra_fields):
  28. extra_fields.setdefault("is_staff", True)
  29. extra_fields.setdefault("is_superuser", True)
  30. extra_fields.setdefault("is_active", True)
  31. if extra_fields.get("is_staff") is not True:
  32. raise ValueError("Superuser must have is_staff=True.")
  33. if extra_fields.get("is_superuser") is not True:
  34. raise ValueError("Superuser must have is_superuser=True.")
  35. return self.create_user(email, password, **extra_fields)
  36. def alert_notification_recipients(self, notification):
  37. """Distinct users associated with a project notification who should receive alerts"""
  38. queryset = self.filter(
  39. organizations_ext_organizationuser__teams__projects__projectalert__notification=notification
  40. )
  41. return self._exclude_recipients(queryset, notification.project_alert.project)
  42. def uptime_monitor_recipients(self, monitor):
  43. """Distinct users associated with a project uptime monitor who should receive alerts"""
  44. queryset = self.filter(
  45. organizations_ext_organizationuser__teams__projects__monitor=monitor
  46. )
  47. return self._exclude_recipients(queryset, monitor.project)
  48. def _exclude_recipients(self, queryset, project):
  49. """Exclude from queryset users who have a preference not to receive notifications"""
  50. return queryset.exclude(
  51. Q(
  52. userprojectalert__project=project,
  53. userprojectalert__status=ProjectAlertStatus.OFF,
  54. )
  55. | Q(subscribe_by_default=False, userprojectalert=None),
  56. ).distinct()
  57. class User(AbstractBaseUser, PermissionsMixin):
  58. email = models.EmailField(unique=True, db_collation="case_insensitive")
  59. name = models.CharField(_("name"), max_length=255, blank=True)
  60. is_staff = models.BooleanField(
  61. _("staff status"),
  62. default=False,
  63. help_text=_("Designates whether the user can log into this site."),
  64. )
  65. is_active = models.BooleanField(
  66. _("active"),
  67. default=True,
  68. help_text=_(
  69. "Designates whether this user should be treated as active. "
  70. "Unselect this instead of deleting accounts."
  71. ),
  72. )
  73. analytics = models.JSONField(null=True, blank=True)
  74. created = models.DateTimeField(auto_now_add=True)
  75. subscribe_by_default = models.BooleanField(
  76. default=True,
  77. help_text="Subscribe to project notifications by default. Overrides project settings",
  78. )
  79. options = models.JSONField(default=dict)
  80. USERNAME_FIELD = "email"
  81. EMAIL_FIELD = "email"
  82. objects = UserManager()
  83. def __str__(self):
  84. return self.email
  85. def get_full_name(self):
  86. return self.email
  87. def get_short_name(self):
  88. return self.email
  89. @property
  90. def username(self):
  91. return self.email
  92. @property
  93. def auth_token(self):
  94. return None
  95. def set_register_analytics_tags(self, tags: str):
  96. """
  97. Set UTM querystring to user's analytics field
  98. """
  99. parsed_tags = parse.parse_qsl(tags.strip("?"))
  100. if self.analytics is None:
  101. self.analytics = {}
  102. self.analytics["register"] = {
  103. tag[0]: tag[1] for tag in parsed_tags if tag[0].startswith("utm_")
  104. }