models.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. from django.conf import settings
  2. from django.db import models, transaction
  3. from django.contrib.auth.models import (
  4. BaseUserManager, AbstractBaseUser
  5. )
  6. from django.utils import timezone
  7. from django.core.exceptions import ValidationError
  8. from desecapi import pdns
  9. import datetime, time
  10. class MyUserManager(BaseUserManager):
  11. def create_user(self, email, password=None, registration_remote_ip=None, captcha_required=False):
  12. """
  13. Creates and saves a User with the given email, date of
  14. birth and password.
  15. """
  16. if not email:
  17. raise ValueError('Users must have an email address')
  18. user = self.model(
  19. email=self.normalize_email(email),
  20. registration_remote_ip=registration_remote_ip,
  21. captcha_required=captcha_required,
  22. )
  23. user.set_password(password)
  24. user.save(using=self._db)
  25. return user
  26. def create_superuser(self, email, password):
  27. """
  28. Creates and saves a superuser with the given email, date of
  29. birth and password.
  30. """
  31. user = self.create_user(email,
  32. password=password
  33. )
  34. user.is_admin = True
  35. user.save(using=self._db)
  36. return user
  37. class User(AbstractBaseUser):
  38. email = models.EmailField(
  39. verbose_name='email address',
  40. max_length=191,
  41. unique=True,
  42. )
  43. is_active = models.BooleanField(default=True)
  44. is_admin = models.BooleanField(default=False)
  45. registration_remote_ip = models.CharField(max_length=1024, blank=True)
  46. captcha_required = models.BooleanField(default=False)
  47. created = models.DateTimeField(auto_now_add=True)
  48. limit_domains = models.IntegerField(default=settings.LIMIT_USER_DOMAIN_COUNT_DEFAULT,null=True,blank=True)
  49. dyn = models.BooleanField(default=True)
  50. objects = MyUserManager()
  51. USERNAME_FIELD = 'email'
  52. REQUIRED_FIELDS = []
  53. def get_full_name(self):
  54. return self.email
  55. def get_short_name(self):
  56. return self.email
  57. def __str__(self):
  58. return self.email
  59. def has_perm(self, perm, obj=None):
  60. "Does the user have a specific permission?"
  61. # Simplest possible answer: Yes, always
  62. return True
  63. def has_module_perms(self, app_label):
  64. "Does the user have permissions to view the app `app_label`?"
  65. # Simplest possible answer: Yes, always
  66. return True
  67. @property
  68. def is_staff(self):
  69. "Is the user a member of staff?"
  70. # Simplest possible answer: All admins are staff
  71. return self.is_admin
  72. def unlock(self):
  73. self.captcha_required = False
  74. for domain in self.domains.all():
  75. domain.pdns_resync()
  76. self.save()
  77. class Domain(models.Model):
  78. created = models.DateTimeField(auto_now_add=True)
  79. updated = models.DateTimeField(null=True)
  80. name = models.CharField(max_length=191, unique=True)
  81. arecord = models.CharField(max_length=255, blank=True)
  82. aaaarecord = models.CharField(max_length=1024, blank=True)
  83. owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='domains')
  84. acme_challenge = models.CharField(max_length=255, blank=True)
  85. _dirtyName = False
  86. _dirtyRecords = False
  87. def __setattr__(self, attrname, val):
  88. setter_func = 'setter_' + attrname
  89. if attrname in self.__dict__ and callable(getattr(self, setter_func, None)):
  90. super(Domain, self).__setattr__(attrname, getattr(self, setter_func)(val))
  91. else:
  92. super(Domain, self).__setattr__(attrname, val)
  93. def setter_name(self, val):
  94. if val != self.name:
  95. self._dirtyName = True
  96. return val
  97. def setter_arecord(self, val):
  98. if val != self.arecord:
  99. self._dirtyRecords = True
  100. return val
  101. def setter_aaaarecord(self, val):
  102. if val != self.aaaarecord:
  103. self._dirtyRecords = True
  104. return val
  105. def setter_acme_challenge(self, val):
  106. if val != self.acme_challenge:
  107. self._dirtyRecords = True
  108. return val
  109. def clean(self):
  110. if self._dirtyName:
  111. raise ValidationError('You must not change the domain name')
  112. def pdns_resync(self):
  113. """
  114. Make sure that pdns gets the latest information about this domain/zone.
  115. Re-Syncing is relatively expensive and should not happen routinely.
  116. """
  117. # Create zone if needed
  118. if not pdns.zone_exists(self.name):
  119. pdns.create_zone(self.name)
  120. # update zone to latest information
  121. pdns.set_dyn_records(self.name, self.arecord, self.aaaarecord, self.acme_challenge)
  122. def pdns_sync(self, new_domain):
  123. """
  124. Command pdns updates as indicated by the local changes.
  125. """
  126. if self.owner.captcha_required:
  127. # suspend all updates
  128. return
  129. # if this zone is new, create it and set dirty flag if necessary
  130. if new_domain:
  131. pdns.create_zone(self.name)
  132. self._dirtyRecords = bool(self.arecord) or bool(self.aaaarecord) or bool(self.acme_challenge)
  133. # make changes if necessary
  134. if self._dirtyRecords:
  135. pdns.set_dyn_records(self.name, self.arecord, self.aaaarecord, self.acme_challenge)
  136. self._dirtyRecords = False
  137. @transaction.atomic
  138. def delete(self, *args, **kwargs):
  139. super(Domain, self).delete(*args, **kwargs)
  140. pdns.delete_zone(self.name)
  141. if self.name.endswith('.dedyn.io'):
  142. pdns.set_rrset('dedyn.io', self.name, 'DS', '')
  143. pdns.set_rrset('dedyn.io', self.name, 'NS', '')
  144. @transaction.atomic
  145. def save(self, *args, **kwargs):
  146. # Record here if this is a new domain (self.pk is only None until we call super.save())
  147. new_domain = self.pk is None
  148. self.updated = timezone.now()
  149. self.clean()
  150. super(Domain, self).save(*args, **kwargs)
  151. self.pdns_sync(new_domain)
  152. class Meta:
  153. ordering = ('created',)
  154. def get_default_value_created():
  155. return timezone.now()
  156. def get_default_value_due():
  157. return timezone.now() + datetime.timedelta(days=7)
  158. def get_default_value_mref():
  159. return "ONDON" + str((timezone.now() - timezone.datetime(1970,1,1,tzinfo=timezone.utc)).total_seconds())
  160. class Donation(models.Model):
  161. created = models.DateTimeField(default=get_default_value_created)
  162. name = models.CharField(max_length=255)
  163. iban = models.CharField(max_length=34)
  164. bic = models.CharField(max_length=11)
  165. amount = models.DecimalField(max_digits=8,decimal_places=2)
  166. message = models.CharField(max_length=255, blank=True)
  167. due = models.DateTimeField(default=get_default_value_due)
  168. mref = models.CharField(max_length=32,default=get_default_value_mref)
  169. email = models.EmailField(max_length=255, blank=True)
  170. def save(self, *args, **kwargs):
  171. self.iban = self.iban[:6] + "xxx" # do NOT save account details
  172. super(Donation, self).save(*args, **kwargs) # Call the "real" save() method.
  173. class Meta:
  174. ordering = ('created',)