testdomains.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. from django.core.urlresolvers import reverse
  2. from rest_framework import status
  3. from rest_framework.test import APITestCase
  4. from .utils import utils
  5. from django.db import transaction
  6. from desecapi.models import Domain
  7. from django.core import mail
  8. import httpretty
  9. from django.conf import settings
  10. class UnauthenticatedDomainTests(APITestCase):
  11. def testExpectUnauthorizedOnGet(self):
  12. url = reverse('domain-list')
  13. response = self.client.get(url, format='json')
  14. self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
  15. def testExpectUnauthorizedOnPost(self):
  16. url = reverse('domain-list')
  17. response = self.client.post(url, format='json')
  18. self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
  19. def testExpectUnauthorizedOnPut(self):
  20. url = reverse('domain-detail', args=(1,))
  21. response = self.client.put(url, format='json')
  22. self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
  23. def testExpectUnauthorizedOnDelete(self):
  24. url = reverse('domain-detail', args=(1,))
  25. response = self.client.delete(url, format='json')
  26. self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
  27. class AuthenticatedDomainTests(APITestCase):
  28. def setUp(self):
  29. if not hasattr(self, 'owner'):
  30. self.owner = utils.createUser()
  31. self.ownedDomains = [utils.createDomain(self.owner), utils.createDomain(self.owner)]
  32. self.otherDomains = [utils.createDomain(), utils.createDomain()]
  33. self.token = utils.createToken(user=self.owner)
  34. self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.token)
  35. def testExpectOnlyOwnedDomains(self):
  36. url = reverse('domain-list')
  37. response = self.client.get(url, format='json')
  38. self.assertEqual(response.status_code, status.HTTP_200_OK)
  39. self.assertEqual(len(response.data), 2)
  40. self.assertEqual(response.data[0]['name'], self.ownedDomains[0].name)
  41. self.assertEqual(response.data[1]['name'], self.ownedDomains[1].name)
  42. def testCanDeleteOwnedDomain(self):
  43. url = reverse('domain-detail', args=(self.ownedDomains[1].pk,))
  44. response = self.client.delete(url)
  45. self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
  46. response = self.client.get(url)
  47. self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
  48. def testCantDeleteOtherDomains(self):
  49. url = reverse('domain-detail', args=(self.otherDomains[1].pk,))
  50. response = self.client.delete(url)
  51. self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
  52. def testCanGetOwnedDomains(self):
  53. url = reverse('domain-detail', args=(self.ownedDomains[1].pk,))
  54. response = self.client.get(url)
  55. self.assertEqual(response.status_code, status.HTTP_200_OK)
  56. self.assertEqual(response.data['name'], self.ownedDomains[1].name)
  57. def testCantGetOtherDomains(self):
  58. url = reverse('domain-detail', args=(self.otherDomains[1].pk,))
  59. response = self.client.get(url)
  60. self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
  61. def testCanPutOwnedDomain(self):
  62. url = reverse('domain-detail', args=(self.ownedDomains[1].pk,))
  63. response = self.client.get(url)
  64. newname = utils.generateDomainname()
  65. response.data['name'] = newname
  66. response = self.client.put(url, response.data)
  67. self.assertEqual(response.status_code, status.HTTP_200_OK)
  68. response = self.client.get(url)
  69. self.assertEqual(response.status_code, status.HTTP_200_OK)
  70. self.assertEqual(response.data['name'], newname)
  71. def testCantPutOtherDomains(self):
  72. url = reverse('domain-detail', args=(self.otherDomains[1].pk,))
  73. response = self.client.put(url, {})
  74. self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
  75. def testCanPostDomains(self):
  76. url = reverse('domain-list')
  77. data = {'name': utils.generateDomainname()}
  78. response = self.client.post(url, data)
  79. self.assertEqual(response.status_code, status.HTTP_201_CREATED)
  80. self.assertEqual(len(mail.outbox), 0)
  81. def testCantPostSameDomainTwice(self):
  82. url = reverse('domain-list')
  83. data = {'name': utils.generateDomainname()}
  84. response = self.client.post(url, data)
  85. self.assertEqual(response.status_code, status.HTTP_201_CREATED)
  86. response = self.client.post(url, data)
  87. self.assertEqual(response.status_code, status.HTTP_409_CONFLICT)
  88. def testCanPostComplicatedDomains(self):
  89. url = reverse('domain-list')
  90. data = {'name': 'very.long.domain.name.' + utils.generateDomainname()}
  91. response = self.client.post(url, data)
  92. self.assertEqual(response.status_code, status.HTTP_201_CREATED)
  93. def testCanUpdateARecord(self):
  94. url = reverse('domain-detail', args=(self.ownedDomains[1].pk,))
  95. response = self.client.get(url)
  96. response.data['arecord'] = '10.13.3.7'
  97. response = self.client.put(url, response.data)
  98. self.assertEqual(response.status_code, status.HTTP_200_OK)
  99. response = self.client.get(url)
  100. self.assertEqual(response.status_code, status.HTTP_200_OK)
  101. self.assertEqual(response.data['arecord'], '10.13.3.7')
  102. def testCanUpdateAAAARecord(self):
  103. url = reverse('domain-detail', args=(self.ownedDomains[1].pk,))
  104. response = self.client.get(url)
  105. response.data['aaaarecord'] = 'fe80::a11:10ff:fee0:ff77'
  106. response = self.client.put(url, response.data)
  107. self.assertEqual(response.status_code, status.HTTP_200_OK)
  108. response = self.client.get(url)
  109. self.assertEqual(response.status_code, status.HTTP_200_OK)
  110. self.assertEqual(response.data['aaaarecord'], 'fe80::a11:10ff:fee0:ff77')
  111. def testPostingCausesPdnsAPICall(self):
  112. httpretty.enable()
  113. httpretty.register_uri(httpretty.POST, settings.POWERDNS_API + '/zones')
  114. url = reverse('domain-list')
  115. data = {'name': utils.generateDomainname()}
  116. response = self.client.post(url, data)
  117. self.assertTrue(data['name'] in httpretty.last_request().parsed_body)
  118. self.assertTrue('ns1.desec.io' in httpretty.last_request().parsed_body)
  119. def testPostingWithRecordsCausesPdnsAPIPatch(self):
  120. name = utils.generateDomainname()
  121. httpretty.enable()
  122. httpretty.register_uri(httpretty.POST, settings.POWERDNS_API + '/zones')
  123. httpretty.register_uri(httpretty.PATCH, settings.POWERDNS_API + '/zones/' + name + '.')
  124. url = reverse('domain-list')
  125. data = {'name': name, 'arecord': '1.3.3.7', 'aaaarecord': 'dead::beef'}
  126. response = self.client.post(url, data)
  127. self.assertEqual(httpretty.last_request().method, 'PATCH')
  128. self.assertTrue(data['name'] in httpretty.last_request().parsed_body)
  129. self.assertTrue('1.3.3.7' in httpretty.last_request().parsed_body)
  130. self.assertTrue('dead::beef' in httpretty.last_request().parsed_body)
  131. def testUpdateingCausesPdnsAPICall(self):
  132. url = reverse('domain-detail', args=(self.ownedDomains[1].pk,))
  133. response = self.client.get(url)
  134. httpretty.enable()
  135. httpretty.register_uri(httpretty.PATCH, settings.POWERDNS_API + '/zones/' + response.data['name'] + '.')
  136. response.data['arecord'] = '10.13.3.7'
  137. response = self.client.put(url, response.data)
  138. self.assertTrue('10.13.3.7' in httpretty.last_request().parsed_body)
  139. def testDomainDetailURL(self):
  140. url = reverse('domain-detail', args=(self.ownedDomains[1].pk,))
  141. urlByName = reverse('domain-detail/byName', args=(self.ownedDomains[1].name,))
  142. self.assertTrue(("/%d" % self.ownedDomains[1].pk) in url)
  143. self.assertTrue("/" + self.ownedDomains[1].name in urlByName)
  144. class AuthenticatedDynDomainTests(APITestCase):
  145. def setUp(self):
  146. if not hasattr(self, 'owner'):
  147. self.owner = utils.createUser(dyn=True)
  148. self.ownedDomains = [utils.createDomain(self.owner, dyn=True), utils.createDomain(self.owner, dyn=True)]
  149. self.otherDomains = [utils.createDomain(), utils.createDomain()]
  150. self.token = utils.createToken(user=self.owner)
  151. self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.token)
  152. def testCanPostDynDomains(self):
  153. url = reverse('domain-list')
  154. data = {'name': utils.generateDynDomainname()}
  155. response = self.client.post(url, data)
  156. email = str(mail.outbox[0].message())
  157. self.assertEqual(response.status_code, status.HTTP_201_CREATED)
  158. self.assertEqual(len(mail.outbox), 1)
  159. self.assertTrue(data['name'] in email)
  160. self.assertTrue(self.token in email)
  161. def testCantPostNonDynDomains(self):
  162. url = reverse('domain-list')
  163. data = {'name': utils.generateDomainname()}
  164. response = self.client.post(url, data)
  165. self.assertEqual(response.status_code, status.HTTP_409_CONFLICT)
  166. data = {'name': 'very.long.domain.' + utils.generateDynDomainname()}
  167. response = self.client.post(url, data)
  168. self.assertEqual(response.status_code, status.HTTP_409_CONFLICT)
  169. def testLimitDynDomains(self):
  170. httpretty.enable()
  171. httpretty.register_uri(httpretty.POST, settings.POWERDNS_API + '/zones')
  172. outboxlen = len(mail.outbox)
  173. url = reverse('domain-list')
  174. for i in range(settings.LIMIT_USER_DOMAIN_COUNT_DEFAULT-2):
  175. data = {'name': utils.generateDynDomainname()}
  176. response = self.client.post(url, data)
  177. self.assertEqual(response.status_code, status.HTTP_201_CREATED)
  178. self.assertEqual(len(mail.outbox), outboxlen+i+1)
  179. data = {'name': utils.generateDynDomainname()}
  180. response = self.client.post(url, data)
  181. self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
  182. self.assertEqual(len(mail.outbox), outboxlen + settings.LIMIT_USER_DOMAIN_COUNT_DEFAULT-2)
  183. def testCantUseInvalidCharactersInDomainNamePDNS(self):
  184. httpretty.enable()
  185. httpretty.register_uri(httpretty.POST, settings.POWERDNS_API + '/zones')
  186. outboxlen = len(mail.outbox)
  187. invalidnames = [
  188. 'with space.dedyn.io',
  189. 'another space.de',
  190. ' spaceatthebeginning.com',
  191. 'percentage%sign.com',
  192. '%percentagesign.dedyn.io',
  193. 'slash/desec.io',
  194. '/slashatthebeginning.dedyn.io',
  195. '\\backslashatthebeginning.dedyn.io',
  196. 'backslash\\inthemiddle.at',
  197. '@atsign.com',
  198. 'at@sign.com',
  199. ]
  200. url = reverse('domain-list')
  201. for domainname in invalidnames:
  202. data = {'name': domainname}
  203. response = self.client.post(url, data)
  204. self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
  205. self.assertEqual(len(mail.outbox), outboxlen)