test_mau.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2018 New Vector Ltd
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. """Tests REST events for /rooms paths."""
  16. import json
  17. from mock import Mock
  18. from synapse.api.constants import LoginType
  19. from synapse.api.errors import Codes, HttpResponseException, SynapseError
  20. from synapse.rest.client.v2_alpha import register, sync
  21. from tests import unittest
  22. class TestMauLimit(unittest.HomeserverTestCase):
  23. servlets = [register.register_servlets, sync.register_servlets]
  24. def make_homeserver(self, reactor, clock):
  25. self.hs = self.setup_test_homeserver(
  26. "red", http_client=None, federation_client=Mock()
  27. )
  28. self.store = self.hs.get_datastore()
  29. self.hs.config.registrations_require_3pid = []
  30. self.hs.config.enable_registration_captcha = False
  31. self.hs.config.recaptcha_public_key = []
  32. self.hs.config.limit_usage_by_mau = True
  33. self.hs.config.hs_disabled = False
  34. self.hs.config.max_mau_value = 2
  35. self.hs.config.mau_trial_days = 0
  36. self.hs.config.server_notices_mxid = "@server:red"
  37. self.hs.config.server_notices_mxid_display_name = None
  38. self.hs.config.server_notices_mxid_avatar_url = None
  39. self.hs.config.server_notices_room_name = "Test Server Notice Room"
  40. return self.hs
  41. def test_simple_deny_mau(self):
  42. # Create and sync so that the MAU counts get updated
  43. token1 = self.create_user("kermit1")
  44. self.do_sync_for_user(token1)
  45. token2 = self.create_user("kermit2")
  46. self.do_sync_for_user(token2)
  47. # We've created and activated two users, we shouldn't be able to
  48. # register new users
  49. with self.assertRaises(SynapseError) as cm:
  50. self.create_user("kermit3")
  51. e = cm.exception
  52. self.assertEqual(e.code, 403)
  53. self.assertEqual(e.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
  54. def test_allowed_after_a_month_mau(self):
  55. # Create and sync so that the MAU counts get updated
  56. token1 = self.create_user("kermit1")
  57. self.do_sync_for_user(token1)
  58. token2 = self.create_user("kermit2")
  59. self.do_sync_for_user(token2)
  60. # Advance time by 31 days
  61. self.reactor.advance(31 * 24 * 60 * 60)
  62. self.store.reap_monthly_active_users()
  63. self.reactor.advance(0)
  64. # We should be able to register more users
  65. token3 = self.create_user("kermit3")
  66. self.do_sync_for_user(token3)
  67. def test_trial_delay(self):
  68. self.hs.config.mau_trial_days = 1
  69. # We should be able to register more than the limit initially
  70. token1 = self.create_user("kermit1")
  71. self.do_sync_for_user(token1)
  72. token2 = self.create_user("kermit2")
  73. self.do_sync_for_user(token2)
  74. token3 = self.create_user("kermit3")
  75. self.do_sync_for_user(token3)
  76. # Advance time by 2 days
  77. self.reactor.advance(2 * 24 * 60 * 60)
  78. # Two users should be able to sync
  79. self.do_sync_for_user(token1)
  80. self.do_sync_for_user(token2)
  81. # But the third should fail
  82. with self.assertRaises(SynapseError) as cm:
  83. self.do_sync_for_user(token3)
  84. e = cm.exception
  85. self.assertEqual(e.code, 403)
  86. self.assertEqual(e.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
  87. # And new registrations are now denied too
  88. with self.assertRaises(SynapseError) as cm:
  89. self.create_user("kermit4")
  90. e = cm.exception
  91. self.assertEqual(e.code, 403)
  92. self.assertEqual(e.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
  93. def test_trial_users_cant_come_back(self):
  94. self.hs.config.mau_trial_days = 1
  95. # We should be able to register more than the limit initially
  96. token1 = self.create_user("kermit1")
  97. self.do_sync_for_user(token1)
  98. token2 = self.create_user("kermit2")
  99. self.do_sync_for_user(token2)
  100. token3 = self.create_user("kermit3")
  101. self.do_sync_for_user(token3)
  102. # Advance time by 2 days
  103. self.reactor.advance(2 * 24 * 60 * 60)
  104. # Two users should be able to sync
  105. self.do_sync_for_user(token1)
  106. self.do_sync_for_user(token2)
  107. # Advance by 2 months so everyone falls out of MAU
  108. self.reactor.advance(60 * 24 * 60 * 60)
  109. self.store.reap_monthly_active_users()
  110. self.reactor.advance(0)
  111. # We can create as many new users as we want
  112. token4 = self.create_user("kermit4")
  113. self.do_sync_for_user(token4)
  114. token5 = self.create_user("kermit5")
  115. self.do_sync_for_user(token5)
  116. token6 = self.create_user("kermit6")
  117. self.do_sync_for_user(token6)
  118. # users 2 and 3 can come back to bring us back up to MAU limit
  119. self.do_sync_for_user(token2)
  120. self.do_sync_for_user(token3)
  121. # New trial users can still sync
  122. self.do_sync_for_user(token4)
  123. self.do_sync_for_user(token5)
  124. self.do_sync_for_user(token6)
  125. # But old user cant
  126. with self.assertRaises(SynapseError) as cm:
  127. self.do_sync_for_user(token1)
  128. e = cm.exception
  129. self.assertEqual(e.code, 403)
  130. self.assertEqual(e.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
  131. def test_tracked_but_not_limited(self):
  132. self.hs.config.max_mau_value = 1 # should not matter
  133. self.hs.config.limit_usage_by_mau = False
  134. self.hs.config.mau_stats_only = True
  135. # Simply being able to create 2 users indicates that the
  136. # limit was not reached.
  137. token1 = self.create_user("kermit1")
  138. self.do_sync_for_user(token1)
  139. token2 = self.create_user("kermit2")
  140. self.do_sync_for_user(token2)
  141. # We do want to verify that the number of tracked users
  142. # matches what we want though
  143. count = self.store.get_monthly_active_count()
  144. self.reactor.advance(100)
  145. self.assertEqual(2, self.successResultOf(count))
  146. def create_user(self, localpart):
  147. request_data = json.dumps(
  148. {
  149. "username": localpart,
  150. "password": "monkey",
  151. "auth": {"type": LoginType.DUMMY},
  152. }
  153. )
  154. request, channel = self.make_request("POST", "/register", request_data)
  155. self.render(request)
  156. if channel.code != 200:
  157. raise HttpResponseException(
  158. channel.code, channel.result["reason"], channel.result["body"]
  159. ).to_synapse_error()
  160. access_token = channel.json_body["access_token"]
  161. return access_token
  162. def do_sync_for_user(self, token):
  163. request, channel = self.make_request("GET", "/sync", access_token=token)
  164. self.render(request)
  165. if channel.code != 200:
  166. raise HttpResponseException(
  167. channel.code, channel.result["reason"], channel.result["body"]
  168. ).to_synapse_error()