class EmailAddress(models.Model): """ Only store the local part, append the domain based on the GSUITE_DOMAIN setting. """ email = models.CharField( max_length=128, primary_key=True, validators=[ RegexValidator(regex=EmailValidator.user_regex), ReservedNameValidator(), ], ) def is_assigned(self, new_owner=None): """ Use the new_owner to make the validation pass with the same as the current owner. """ fields = ["email_list", "user", "abakusgroup"] def check_reverse(field): try: owner = getattr(self, field, None) if owner and new_owner: return not owner == new_owner elif owner: return True except ObjectDoesNotExist: pass for field in fields: if check_reverse(field): return True return False
def validate_email_address_content(email_address): """Make sure we only create valid emails.""" regex_validator = RegexValidator(regex=EmailValidator.user_regex) reserved_valdator = ReservedNameValidator() regex_validator(email_address.email) reserved_valdator(email_address.email)
class User(PasswordHashUser, GSuiteAddress, AbstractBaseUser, PersistentModel, PermissionsMixin): """ Abakus user model, uses AbstractBaseUser because we use a custom PermissionsMixin. """ username = models.CharField( max_length=50, unique=True, db_index=True, help_text= "Required. 50 characters or fewer. Letters, digits and _ only.", validators=[username_validator, ReservedNameValidator()], error_messages={"unique": "A user with that username already exists."}, ) student_username = models.CharField( max_length=30, unique=True, null=True, help_text="30 characters or fewer. Letters, digits and _ only.", validators=[username_validator, ReservedNameValidator()], error_messages={ "unique": "A user has already verified that student username." }, ) first_name = models.CharField("first name", max_length=50, blank=True) last_name = models.CharField("last name", max_length=30, blank=True) allergies = models.CharField("allergies", max_length=100, blank=True) email = models.EmailField( unique=True, validators=[email_blacklist_validator], error_messages={"unique": "A user with that email already exists."}, ) email_lists_enabled = models.BooleanField(default=True) gender = models.CharField(max_length=50, choices=constants.GENDERS) picture = FileField(related_name="user_pictures") is_active = models.BooleanField( default=True, help_text="Designates whether this user should be treated as " "active. Unselect this instead of deleting accounts.", ) date_joined = models.DateTimeField("date joined", default=timezone.now) date_bumped = models.DateTimeField("date bumped", null=True, default=None) objects = AbakusUserManager() USERNAME_FIELD = "username" REQUIRED_FIELDS = ["email"] backend = "lego.apps.permissions.backends.AbakusPermissionBackend" class Meta: permission_handler = UserPermissionHandler() def clean(self): self.student_username = self.student_username.lower() super(User, self).clean() def get_full_name(self): return f"{self.first_name} {self.last_name}".strip() def get_default_picture(self): if self.gender == constants.MALE: return "default_male_avatar.png" elif self.gender == constants.FEMALE: return "default_female_avatar.png" else: return "default_other_avatar.png" @property def full_name(self): return self.get_full_name() @property def grade(self): return self.abakus_groups.filter(type=constants.GROUP_GRADE).first() @property def profile_picture(self): return self.picture_id or self.get_default_picture() @property def email_address(self): """ Return the address used to reach the user. Some users have a GSuite address and this function is used to decide the correct address to use. """ internal_address = self.internal_email_address if self.is_active and self.crypt_password_hash and internal_address: # Return the internal address if all requirements for a GSuite account are met. return internal_address return self.email @profile_picture.setter def profile_picture(self, value): self.picture = value def is_verified_student(self): return self.student_username is not None def get_short_name(self): return self.first_name def natural_key(self): return (self.username, ) def number_of_penalties(self): # Returns the total penalty weight for this user count = (Penalty.objects.valid().filter(user=self).aggregate( models.Sum("weight"))["weight__sum"]) return count or 0 def restricted_lookup(self): """ Restricted mail """ return [self], [] def announcement_lookup(self): return [self] def unanswered_surveys(self): from lego.apps.surveys.models import Survey from lego.apps.events.models import Registration registrations = Registration.objects.filter(user_id=self.id, presence=PRESENT) unanswered_surveys = (Survey.objects.filter( event__registrations__in=registrations, active_from__lte=timezone.now(), template_type__isnull=True, ).exclude(submissions__user__in=[self]).prefetch_related( "event__registrations", "submissions__user")) return list(unanswered_surveys.values_list("id", flat=True))
class User(PasswordHashUser, GSuiteAddress, AbstractBaseUser, PersistentModel, PermissionsMixin): """ Abakus user model, uses AbstractBaseUser because we use a custom PermissionsMixin. """ username = models.CharField( max_length=50, unique=True, db_index=True, help_text= 'Required. 50 characters or fewer. Letters, digits and _ only.', validators=[username_validator, ReservedNameValidator()], error_messages={ 'unique': 'A user with that username already exists.', }) student_username = models.CharField( max_length=30, unique=True, null=True, help_text='30 characters or fewer. Letters, digits and _ only.', validators=[username_validator, ReservedNameValidator()], error_messages={ 'unique': 'A user has already verified that student username.', }) first_name = models.CharField('first name', max_length=50, blank=True) last_name = models.CharField('last name', max_length=30, blank=True) allergies = models.CharField('allergies', max_length=30, blank=True) email = models.EmailField(unique=True, validators=[email_blacklist_validator], error_messages={ 'unique': 'A user with that email already exists.', }) email_lists_enabled = models.BooleanField(default=True) gender = models.CharField(max_length=50, choices=constants.GENDERS) picture = FileField(related_name='user_pictures') is_active = models.BooleanField( default=True, help_text='Designates whether this user should be treated as ' 'active. Unselect this instead of deleting accounts.') date_joined = models.DateTimeField('date joined', default=timezone.now) objects = AbakusUserManager() USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['email'] backend = 'lego.apps.permissions.backends.AbakusPermissionBackend' class Meta: permission_handler = UserPermissionHandler() def clean(self): self.student_username = self.student_username.lower() super(User, self).clean() def get_full_name(self): return f'{self.first_name} {self.last_name}'.strip() def get_default_picture(self): if self.gender == constants.MALE: return 'default_male_avatar.png' elif self.gender == constants.FEMALE: return 'default_female_avatar.png' else: return 'default_other_avatar.png' @property def full_name(self): return self.get_full_name() @property def grade(self): return self.abakus_groups.filter(type=constants.GROUP_GRADE).first() @property def profile_picture(self): return self.picture_id or self.get_default_picture() @property def email_address(self): """ Return the address used to reach the user. Some users have a GSuite address and this function is used to decide the correct address to use. """ internal_address = self.internal_email_address if self.is_active and self.crypt_password_hash and internal_address: # Return the internal address if all requirements for a GSuite account are met. return internal_address return self.email @profile_picture.setter def profile_picture(self, value): self.picture = value def is_verified_student(self): return self.student_username is not None def get_short_name(self): return self.first_name def natural_key(self): return self.username, def number_of_penalties(self): # Returns the total penalty weight for this user count = Penalty.objects.valid().filter(user=self)\ .aggregate(models.Sum('weight'))['weight__sum'] return count or 0 def restricted_lookup(self): """ Restricted mail """ return [self], [] def announcement_lookup(self): return [self]
def get_validators(self): validators = super().get_validators() validators.append(lambda t: validate_tag(t["tag"])) validators.append(lambda t: ReservedNameValidator( reserved_names=["popular"])(t["tag"])) return validators
def get_validators(self): validators = super().get_validators() validators.append(validate_tag) validators.append(ReservedNameValidator(reserved_names=['popular'])) return validators