models.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. from django.conf import settings
  2. from django.db import models
  3. from django.contrib.auth.models import (
  4. BaseUserManager, AbstractBaseUser
  5. )
  6. from django.utils import timezone
  7. import requests
  8. import json
  9. import subprocess
  10. import os
  11. import datetime, time
  12. class MyUserManager(BaseUserManager):
  13. def create_user(self, email, password=None):
  14. """
  15. Creates and saves a User with the given email, date of
  16. birth and password.
  17. """
  18. if not email:
  19. raise ValueError('Users must have an email address')
  20. user = self.model(
  21. email=self.normalize_email(email),
  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=255,
  41. unique=True,
  42. )
  43. is_active = models.BooleanField(default=True)
  44. is_admin = models.BooleanField(default=False)
  45. objects = MyUserManager()
  46. USERNAME_FIELD = 'email'
  47. REQUIRED_FIELDS = []
  48. def get_full_name(self):
  49. return self.email
  50. def get_short_name(self):
  51. return self.email
  52. def __str__(self):
  53. return self.email
  54. def has_perm(self, perm, obj=None):
  55. "Does the user have a specific permission?"
  56. # Simplest possible answer: Yes, always
  57. return True
  58. def has_module_perms(self, app_label):
  59. "Does the user have permissions to view the app `app_label`?"
  60. # Simplest possible answer: Yes, always
  61. return True
  62. @property
  63. def is_staff(self):
  64. "Is the user a member of staff?"
  65. # Simplest possible answer: All admins are staff
  66. return self.is_admin
  67. class Domain(models.Model):
  68. created = models.DateTimeField(auto_now_add=True)
  69. updated = models.DateTimeField(null=True)
  70. name = models.CharField(max_length=255, unique=True)
  71. arecord = models.CharField(max_length=255, blank=True)
  72. aaaarecord = models.CharField(max_length=1024, blank=True)
  73. dyn = models.BooleanField(default=False)
  74. owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='domains')
  75. headers = {
  76. 'User-Agent': 'desecapi',
  77. 'X-API-Key': settings.POWERDNS_API_TOKEN,
  78. }
  79. def save(self, *args, **kwargs):
  80. if self.id is None:
  81. self.pdnsCreate()
  82. if self.arecord or self.aaaarecord:
  83. self.pdnsUpdate()
  84. else:
  85. orig = Domain.objects.get(id=self.id)
  86. if self.arecord != orig.arecord or self.aaaarecord != orig.aaaarecord:
  87. self.pdnsUpdate()
  88. self.updated = timezone.now()
  89. super(Domain, self).save(*args, **kwargs) # Call the "real" save() method.
  90. def pdnsCreate(self):
  91. payload = {
  92. "name": self.name + ".",
  93. "kind": "master",
  94. "masters": [],
  95. "nameservers": [
  96. "ns1.desec.io.",
  97. "ns2.desec.io."
  98. ]
  99. }
  100. r = requests.post(settings.POWERDNS_API + '/zones', data=json.dumps(payload), headers=self.headers)
  101. if r.status_code < 200 or r.status_code >= 300:
  102. raise Exception(r)
  103. self.postCreateHook()
  104. def pdnsUpdate(self):
  105. if self.arecord:
  106. a = \
  107. {
  108. "records": [
  109. {
  110. "type": "A",
  111. "name": self.name + ".",
  112. "disabled": False,
  113. "content": self.arecord,
  114. }
  115. ],
  116. "ttl": 60,
  117. "changetype": "REPLACE",
  118. "type": "A",
  119. "name": self.name + ".",
  120. }
  121. else:
  122. a = \
  123. {
  124. "changetype": "DELETE",
  125. "type": "A",
  126. "name": self.name + "."
  127. }
  128. if self.aaaarecord:
  129. aaaa = \
  130. {
  131. "records": [
  132. {
  133. "type": "AAAA",
  134. "name": self.name + ".",
  135. "disabled": False,
  136. "content": self.aaaarecord,
  137. }
  138. ],
  139. "ttl": 60,
  140. "changetype": "REPLACE",
  141. "type": "AAAA",
  142. "name": self.name + ".",
  143. }
  144. else:
  145. aaaa = \
  146. {
  147. "changetype": "DELETE",
  148. "type": "AAAA",
  149. "name": self.name + "."
  150. }
  151. payload = { "rrsets": [a, aaaa] }
  152. r = requests.patch(settings.POWERDNS_API + '/zones/' + self.name, data=json.dumps(payload), headers=self.headers)
  153. if r.status_code < 200 or r.status_code >= 300:
  154. raise Exception(r)
  155. def hook(self, cmd):
  156. if not self.name:
  157. raise Exception
  158. env = os.environ.copy()
  159. env['APITOKEN'] = settings.POWERDNS_API_TOKEN
  160. cmd = [cmd, self.name.lower()]
  161. p_hook = subprocess.Popen(cmd,
  162. stdin=subprocess.PIPE,
  163. stdout=subprocess.PIPE,
  164. stderr=subprocess.PIPE,
  165. env=env)
  166. stdout, stderr = p_hook.communicate()
  167. if not p_hook.returncode == 0:
  168. raise Exception((stdout, stderr))
  169. return
  170. def postCreateHook(self):
  171. self.hook(cmd='domain_post_create.sh')
  172. class Meta:
  173. ordering = ('created',)
  174. def get_default_value_created():
  175. return timezone.now()
  176. def get_default_value_due():
  177. return timezone.now() + datetime.timedelta(days=7)
  178. def get_default_value_mref():
  179. return "ONDON" + str((timezone.now() - timezone.datetime(1970,1,1,tzinfo=timezone.utc)).total_seconds())
  180. class Donation(models.Model):
  181. created = models.DateTimeField(default=get_default_value_created)
  182. name = models.CharField(max_length=255)
  183. iban = models.CharField(max_length=34)
  184. bic = models.CharField(max_length=11)
  185. amount = models.DecimalField(max_digits=8,decimal_places=2)
  186. message = models.CharField(max_length=255, blank=True)
  187. due = models.DateTimeField(default=get_default_value_due)
  188. mref = models.CharField(max_length=32,default=get_default_value_mref)
  189. email = models.EmailField(max_length=255, blank=True)
  190. def save(self, *args, **kwargs):
  191. self.iban = self.iban[:6] + "xxx" # do NOT save account details
  192. super(Donation, self).save(*args, **kwargs) # Call the "real" save() method.
  193. class Meta:
  194. ordering = ('created',)