Source code for authentication_service.models

import uuid

from django.conf import settings
from django.contrib.auth import hashers
from django.contrib.auth.models import AbstractUser
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import ugettext as _


GENDER_CHOICES = (
    ("female", _("Female")),
    ("male", _("Male")),
    ("other", _("Other"))
)


# NOTE: Changing AUTH_USER_MODEL will cause migration 0001 from otp_totp to
# break once migrations have already been run once.
[docs]class CoreUser(AbstractUser): id = models.UUIDField(primary_key=True, default=uuid.uuid1, editable=False) email = models.EmailField(_('email address'), blank=True, null=True, unique=True) email_verified = models.BooleanField(default=False) nickname = models.CharField(blank=True, null=True, max_length=30) msisdn = models.CharField(blank=True, null=True, max_length=16) msisdn_verified = models.BooleanField(default=False) gender = models.CharField( max_length=10, blank=True, null=True, choices=GENDER_CHOICES ) birth_date = models.DateField() country = models.ForeignKey(_("Country"), blank=True, null=True) avatar = models.ImageField(blank=True, null=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) organisational_unit = models.ForeignKey( "OrganisationalUnit", blank=True, null=True ) def __init__(self, *args, **kwargs): super(CoreUser, self).__init__(*args, **kwargs) self._original_email = self.email self._original_msisdn = self.msisdn
[docs] def save(self, *args, **kwargs): # If email or msisdn has changed, their verified flags need # to be updated. if self.email != self._original_email: self.email_verified = False if self.msisdn != self._original_msisdn: self.msisdn_verified = False # To prevent unique constaint issues that are not db related, if the # email is an empty string make it None. A None value on forms gets # converted to an empty string somewhere along the line. if self.email == "": self.email = None super(CoreUser, self).save(*args, **kwargs)
@property def has_security_questions(self): return self.usersecurityquestion_set.all() or None
[docs]class Country(models.Model): code = models.CharField(max_length=2, primary_key=True) name = models.CharField(blank=True, null=True, max_length=100) class Meta: verbose_name_plural = _("Countries") def __str__(self): return "%s - %s" % (self.code, self.name)
[docs]class UserSecurityQuestion(models.Model): user = models.ForeignKey("CoreUser") answer = models.TextField() language_code = models.CharField(max_length=7, choices=settings.LANGUAGES) question = models.ForeignKey("SecurityQuestion") # NOTE as always, be aware certain update, create and save paths will never # trigger save() or the post/pre save signals.
[docs] def save(self, *args, **kwargs): # Make use of django built in password hasher, gives us # "check_password" method for comparison later on. In short, salts and # hashes the text. self.answer = hashers.make_password(self.answer.strip().lower()) super(UserSecurityQuestion, self).save(*args, **kwargs)
def __str__(self): return "%s - %s" % (self.language_code, self.question.id)
[docs]class SecurityQuestion(models.Model): question_text = models.TextField(help_text=_("Default question text")) def __str__(self): return self.question_text
[docs]class QuestionLanguageText(models.Model): language_code = models.CharField(max_length=7, choices=settings.LANGUAGES) question = models.ForeignKey( "SecurityQuestion", on_delete=models.CASCADE ) question_text = models.TextField()
[docs] def validate_unique(self, *args, **kwargs): super(QuestionLanguageText, self).validate_unique(*args, **kwargs) if SecurityQuestion.objects.filter( questionlanguagetext__id=self.id).count() > 1: raise ValidationError( _("Question text can not be assigned to more than one question.") )
def __str__(self): return "%s - %s" % (self.language_code, self.question.id)
[docs]class OrganisationalUnit(models.Model): name = models.CharField(max_length=100, unique=True) description = models.TextField() created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True)