PageRenderTime 27ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/src/mailman/app/tests/test_registrar.py

https://gitlab.com/noc0lour/mailman
Python | 268 lines | 177 code | 17 blank | 74 comment | 0 complexity | 033a8a234fb0b96f7a1a37c233f91820 MD5 | raw file
  1. # Copyright (C) 2012-2016 by the Free Software Foundation, Inc.
  2. #
  3. # This file is part of GNU Mailman.
  4. #
  5. # GNU Mailman is free software: you can redistribute it and/or modify it under
  6. # the terms of the GNU General Public License as published by the Free
  7. # Software Foundation, either version 3 of the License, or (at your option)
  8. # any later version.
  9. #
  10. # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
  11. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. # more details.
  14. #
  15. # You should have received a copy of the GNU General Public License along with
  16. # GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
  17. """Test email address registration."""
  18. import unittest
  19. from mailman.app.lifecycle import create_list
  20. from mailman.interfaces.mailinglist import SubscriptionPolicy
  21. from mailman.interfaces.member import MemberRole
  22. from mailman.interfaces.pending import IPendings
  23. from mailman.interfaces.registrar import IRegistrar
  24. from mailman.interfaces.subscriptions import TokenOwner
  25. from mailman.interfaces.usermanager import IUserManager
  26. from mailman.testing.helpers import get_queue_messages
  27. from mailman.testing.layers import ConfigLayer
  28. from mailman.utilities.datetime import now
  29. from zope.component import getUtility
  30. class TestRegistrar(unittest.TestCase):
  31. """Test registration."""
  32. layer = ConfigLayer
  33. def setUp(self):
  34. self._mlist = create_list('ant@example.com')
  35. self._registrar = IRegistrar(self._mlist)
  36. self._pendings = getUtility(IPendings)
  37. self._anne = getUtility(IUserManager).create_address(
  38. 'anne@example.com')
  39. def test_initial_conditions(self):
  40. # Registering a subscription request provides a unique token associated
  41. # with a pendable, and the owner of the token.
  42. self.assertEqual(self._pendings.count, 0)
  43. token, token_owner, member = self._registrar.register(self._anne)
  44. self.assertIsNotNone(token)
  45. self.assertEqual(token_owner, TokenOwner.subscriber)
  46. self.assertIsNone(member)
  47. self.assertEqual(self._pendings.count, 1)
  48. record = self._pendings.confirm(token, expunge=False)
  49. self.assertEqual(record['list_id'], self._mlist.list_id)
  50. self.assertEqual(record['email'], 'anne@example.com')
  51. def test_subscribe(self):
  52. # Registering a subscription request where no confirmation or
  53. # moderation steps are needed, leaves us with no token or owner, since
  54. # there's nothing more to do.
  55. self._mlist.subscription_policy = SubscriptionPolicy.open
  56. self._anne.verified_on = now()
  57. token, token_owner, rmember = self._registrar.register(self._anne)
  58. self.assertIsNone(token)
  59. self.assertEqual(token_owner, TokenOwner.no_one)
  60. member = self._mlist.regular_members.get_member('anne@example.com')
  61. self.assertEqual(rmember, member)
  62. self.assertEqual(member.address, self._anne)
  63. # There's nothing to confirm.
  64. record = self._pendings.confirm(token, expunge=False)
  65. self.assertIsNone(record)
  66. def test_no_such_token(self):
  67. # Given a token which is not in the database, a LookupError is raised.
  68. self._registrar.register(self._anne)
  69. self.assertRaises(LookupError, self._registrar.confirm, 'not-a-token')
  70. def test_confirm_because_verify(self):
  71. # We have a subscription request which requires the user to confirm
  72. # (because she does not have a verified address), but not the moderator
  73. # to approve. Running the workflow gives us a token. Confirming the
  74. # token subscribes the user.
  75. self._mlist.subscription_policy = SubscriptionPolicy.open
  76. token, token_owner, rmember = self._registrar.register(self._anne)
  77. self.assertIsNotNone(token)
  78. self.assertEqual(token_owner, TokenOwner.subscriber)
  79. self.assertIsNone(rmember)
  80. member = self._mlist.regular_members.get_member('anne@example.com')
  81. self.assertIsNone(member)
  82. # Now confirm the subscription.
  83. token, token_owner, rmember = self._registrar.confirm(token)
  84. self.assertIsNone(token)
  85. self.assertEqual(token_owner, TokenOwner.no_one)
  86. member = self._mlist.regular_members.get_member('anne@example.com')
  87. self.assertEqual(rmember, member)
  88. self.assertEqual(member.address, self._anne)
  89. def test_confirm_because_confirm(self):
  90. # We have a subscription request which requires the user to confirm
  91. # (because of list policy), but not the moderator to approve. Running
  92. # the workflow gives us a token. Confirming the token subscribes the
  93. # user.
  94. self._mlist.subscription_policy = SubscriptionPolicy.confirm
  95. self._anne.verified_on = now()
  96. token, token_owner, rmember = self._registrar.register(self._anne)
  97. self.assertIsNotNone(token)
  98. self.assertEqual(token_owner, TokenOwner.subscriber)
  99. self.assertIsNone(rmember)
  100. member = self._mlist.regular_members.get_member('anne@example.com')
  101. self.assertIsNone(member)
  102. # Now confirm the subscription.
  103. token, token_owner, rmember = self._registrar.confirm(token)
  104. self.assertIsNone(token)
  105. self.assertEqual(token_owner, TokenOwner.no_one)
  106. member = self._mlist.regular_members.get_member('anne@example.com')
  107. self.assertEqual(rmember, member)
  108. self.assertEqual(member.address, self._anne)
  109. def test_confirm_because_moderation(self):
  110. # We have a subscription request which requires the moderator to
  111. # approve. Running the workflow gives us a token. Confirming the
  112. # token subscribes the user.
  113. self._mlist.subscription_policy = SubscriptionPolicy.moderate
  114. self._anne.verified_on = now()
  115. token, token_owner, rmember = self._registrar.register(self._anne)
  116. self.assertIsNotNone(token)
  117. self.assertEqual(token_owner, TokenOwner.moderator)
  118. self.assertIsNone(rmember)
  119. member = self._mlist.regular_members.get_member('anne@example.com')
  120. self.assertIsNone(member)
  121. # Now confirm the subscription.
  122. token, token_owner, rmember = self._registrar.confirm(token)
  123. self.assertIsNone(token)
  124. self.assertEqual(token_owner, TokenOwner.no_one)
  125. member = self._mlist.regular_members.get_member('anne@example.com')
  126. self.assertEqual(rmember, member)
  127. self.assertEqual(member.address, self._anne)
  128. def test_confirm_because_confirm_then_moderation(self):
  129. # We have a subscription request which requires the user to confirm
  130. # (because she does not have a verified address) and the moderator to
  131. # approve. Running the workflow gives us a token. Confirming the
  132. # token runs the workflow a little farther, but still gives us a
  133. # token. Confirming again subscribes the user.
  134. self._mlist.subscription_policy = (
  135. SubscriptionPolicy.confirm_then_moderate)
  136. self._anne.verified_on = now()
  137. # Runs until subscription confirmation.
  138. token, token_owner, rmember = self._registrar.register(self._anne)
  139. self.assertIsNotNone(token)
  140. self.assertEqual(token_owner, TokenOwner.subscriber)
  141. self.assertIsNone(rmember)
  142. member = self._mlist.regular_members.get_member('anne@example.com')
  143. self.assertIsNone(member)
  144. # Now confirm the subscription, and wait for the moderator to approve
  145. # the subscription. She is still not subscribed.
  146. new_token, token_owner, rmember = self._registrar.confirm(token)
  147. # The new token, used for the moderator to approve the message, is not
  148. # the same as the old token.
  149. self.assertNotEqual(new_token, token)
  150. self.assertIsNotNone(new_token)
  151. self.assertEqual(token_owner, TokenOwner.moderator)
  152. self.assertIsNone(rmember)
  153. member = self._mlist.regular_members.get_member('anne@example.com')
  154. self.assertIsNone(member)
  155. # Confirm once more, this time as the moderator approving the
  156. # subscription. Now she's a member.
  157. token, token_owner, rmember = self._registrar.confirm(new_token)
  158. self.assertIsNone(token)
  159. self.assertEqual(token_owner, TokenOwner.no_one)
  160. member = self._mlist.regular_members.get_member('anne@example.com')
  161. self.assertEqual(rmember, member)
  162. self.assertEqual(member.address, self._anne)
  163. def test_confirm_then_moderate_with_different_tokens(self):
  164. # Ensure that the confirmation token the user sees when they have to
  165. # confirm their subscription is different than the token the moderator
  166. # sees when they approve the subscription. This prevents the user
  167. # from using a replay attack to subvert moderator approval.
  168. self._mlist.subscription_policy = (
  169. SubscriptionPolicy.confirm_then_moderate)
  170. self._anne.verified_on = now()
  171. # Runs until subscription confirmation.
  172. token, token_owner, rmember = self._registrar.register(self._anne)
  173. self.assertIsNotNone(token)
  174. self.assertEqual(token_owner, TokenOwner.subscriber)
  175. self.assertIsNone(rmember)
  176. member = self._mlist.regular_members.get_member('anne@example.com')
  177. self.assertIsNone(member)
  178. # Now confirm the subscription, and wait for the moderator to approve
  179. # the subscription. She is still not subscribed.
  180. new_token, token_owner, rmember = self._registrar.confirm(token)
  181. # The status is not true because the user has not yet been subscribed
  182. # to the mailing list.
  183. self.assertIsNotNone(new_token)
  184. self.assertEqual(token_owner, TokenOwner.moderator)
  185. self.assertIsNone(rmember)
  186. member = self._mlist.regular_members.get_member('anne@example.com')
  187. self.assertIsNone(member)
  188. # The new token is different than the old token.
  189. self.assertNotEqual(token, new_token)
  190. # Trying to confirm with the old token does not work.
  191. self.assertRaises(LookupError, self._registrar.confirm, token)
  192. # Confirm once more, this time with the new token, as the moderator
  193. # approving the subscription. Now she's a member.
  194. done_token, token_owner, rmember = self._registrar.confirm(new_token)
  195. # The token is None, signifying that the member has been subscribed.
  196. self.assertIsNone(done_token)
  197. self.assertEqual(token_owner, TokenOwner.no_one)
  198. member = self._mlist.regular_members.get_member('anne@example.com')
  199. self.assertEqual(rmember, member)
  200. self.assertEqual(member.address, self._anne)
  201. def test_discard_waiting_for_confirmation(self):
  202. # While waiting for a user to confirm their subscription, we discard
  203. # the workflow.
  204. self._mlist.subscription_policy = SubscriptionPolicy.confirm
  205. self._anne.verified_on = now()
  206. # Runs until subscription confirmation.
  207. token, token_owner, rmember = self._registrar.register(self._anne)
  208. self.assertIsNotNone(token)
  209. self.assertEqual(token_owner, TokenOwner.subscriber)
  210. self.assertIsNone(rmember)
  211. member = self._mlist.regular_members.get_member('anne@example.com')
  212. self.assertIsNone(member)
  213. # Now discard the subscription request.
  214. self._registrar.discard(token)
  215. # Trying to confirm the token now results in an exception.
  216. self.assertRaises(LookupError, self._registrar.confirm, token)
  217. def test_admin_notify_mchanges(self):
  218. # When a user gets subscribed via the subscription policy workflow,
  219. # the list administrators get an email notification.
  220. self._mlist.subscription_policy = SubscriptionPolicy.open
  221. self._mlist.admin_notify_mchanges = True
  222. self._mlist.send_welcome_message = False
  223. token, token_owner, member = self._registrar.register(
  224. self._anne, pre_verified=True)
  225. # Anne is now a member.
  226. self.assertEqual(member.address.email, 'anne@example.com')
  227. # And there's a notification email waiting for Bart.
  228. items = get_queue_messages('virgin', expected_count=1)
  229. message = items[0].msg
  230. self.assertEqual(message['To'], 'ant-owner@example.com')
  231. self.assertEqual(message['Subject'], 'Ant subscription notification')
  232. self.assertEqual(message.get_payload(), """\
  233. anne@example.com has been successfully subscribed to Ant.""")
  234. def test_no_admin_notify_mchanges(self):
  235. # Even when a user gets subscribed via the subscription policy
  236. # workflow, the list administrators won't get an email notification if
  237. # they don't want one.
  238. self._mlist.subscription_policy = SubscriptionPolicy.open
  239. self._mlist.admin_notify_mchanges = False
  240. self._mlist.send_welcome_message = False
  241. # Bart is an administrator of the mailing list.
  242. bart = getUtility(IUserManager).create_address(
  243. 'bart@example.com', 'Bart Person')
  244. self._mlist.subscribe(bart, MemberRole.owner)
  245. token, token_owner, member = self._registrar.register(
  246. self._anne, pre_verified=True)
  247. # Anne is now a member.
  248. self.assertEqual(member.address.email, 'anne@example.com')
  249. # There's no notification email waiting for Bart.
  250. get_queue_messages('virgin', expected_count=0)