models.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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 Exists, OuterRef
  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. from apps.projects.models import UserProjectAlert
  51. explicit_off = UserProjectAlert.objects.filter(
  52. user=OuterRef("pk"), project=project, status=ProjectAlertStatus.OFF
  53. )
  54. has_project_alert = UserProjectAlert.objects.filter(
  55. user=OuterRef("pk"), project=project
  56. )
  57. return queryset.exclude(
  58. Exists(explicit_off)
  59. | (~Exists(has_project_alert) & ~models.Q(subscribe_by_default=True))
  60. ).distinct()
  61. class User(AbstractBaseUser, PermissionsMixin):
  62. email = models.EmailField(unique=True, db_collation="case_insensitive")
  63. name = models.CharField(_("name"), max_length=255, blank=True)
  64. is_staff = models.BooleanField(
  65. _("staff status"),
  66. default=False,
  67. help_text=_("Designates whether the user can log into this site."),
  68. )
  69. is_active = models.BooleanField(
  70. _("active"),
  71. default=True,
  72. help_text=_(
  73. "Designates whether this user should be treated as active. "
  74. "Unselect this instead of deleting accounts."
  75. ),
  76. )
  77. analytics = models.JSONField(null=True, blank=True)
  78. created = models.DateTimeField(auto_now_add=True)
  79. subscribe_by_default = models.BooleanField(
  80. default=True,
  81. help_text="Subscribe to project notifications by default. Overrides project settings",
  82. )
  83. options = models.JSONField(default=dict)
  84. USERNAME_FIELD = "email"
  85. EMAIL_FIELD = "email"
  86. objects = UserManager()
  87. def __str__(self):
  88. return self.email
  89. def get_full_name(self):
  90. return self.email
  91. def get_short_name(self):
  92. return self.email
  93. @property
  94. def username(self):
  95. return self.email
  96. @property
  97. def auth_token(self):
  98. return None
  99. def set_register_analytics_tags(self, tags: str):
  100. """
  101. Set UTM querystring to user's analytics field
  102. """
  103. parsed_tags = parse.parse_qsl(tags.strip("?"))
  104. if self.analytics is None:
  105. self.analytics = {}
  106. self.analytics["register"] = {
  107. tag[0]: tag[1] for tag in parsed_tags if tag[0].startswith("utm_")
  108. }