test_mau.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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 synapse.api.constants import LoginType
  18. from synapse.api.errors import Codes, HttpResponseException, SynapseError
  19. from synapse.rest.client.v2_alpha import register, sync
  20. from tests import unittest
  21. from tests.unittest import override_config
  22. from tests.utils import default_config
  23. class TestMauLimit(unittest.HomeserverTestCase):
  24. servlets = [register.register_servlets, sync.register_servlets]
  25. def default_config(self):
  26. config = default_config("test")
  27. config.update(
  28. {
  29. "registrations_require_3pid": [],
  30. "limit_usage_by_mau": True,
  31. "max_mau_value": 2,
  32. "mau_trial_days": 0,
  33. "server_notices": {
  34. "system_mxid_localpart": "server",
  35. "room_name": "Test Server Notice Room",
  36. },
  37. }
  38. )
  39. # apply any additional config which was specified via the override_config
  40. # decorator.
  41. if self._extra_config is not None:
  42. config.update(self._extra_config)
  43. return config
  44. def prepare(self, reactor, clock, homeserver):
  45. self.store = homeserver.get_datastore()
  46. def test_simple_deny_mau(self):
  47. # Create and sync so that the MAU counts get updated
  48. token1 = self.create_user("kermit1")
  49. self.do_sync_for_user(token1)
  50. token2 = self.create_user("kermit2")
  51. self.do_sync_for_user(token2)
  52. # check we're testing what we think we are: there should be two active users
  53. self.assertEqual(self.get_success(self.store.get_monthly_active_count()), 2)
  54. # We've created and activated two users, we shouldn't be able to
  55. # register new users
  56. with self.assertRaises(SynapseError) as cm:
  57. self.create_user("kermit3")
  58. e = cm.exception
  59. self.assertEqual(e.code, 403)
  60. self.assertEqual(e.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
  61. def test_allowed_after_a_month_mau(self):
  62. # Create and sync so that the MAU counts get updated
  63. token1 = self.create_user("kermit1")
  64. self.do_sync_for_user(token1)
  65. token2 = self.create_user("kermit2")
  66. self.do_sync_for_user(token2)
  67. # Advance time by 31 days
  68. self.reactor.advance(31 * 24 * 60 * 60)
  69. self.store.reap_monthly_active_users()
  70. self.reactor.advance(0)
  71. # We should be able to register more users
  72. token3 = self.create_user("kermit3")
  73. self.do_sync_for_user(token3)
  74. @override_config({"mau_trial_days": 1})
  75. def test_trial_delay(self):
  76. # We should be able to register more than the limit initially
  77. token1 = self.create_user("kermit1")
  78. self.do_sync_for_user(token1)
  79. token2 = self.create_user("kermit2")
  80. self.do_sync_for_user(token2)
  81. token3 = self.create_user("kermit3")
  82. self.do_sync_for_user(token3)
  83. # Advance time by 2 days
  84. self.reactor.advance(2 * 24 * 60 * 60)
  85. # Two users should be able to sync
  86. self.do_sync_for_user(token1)
  87. self.do_sync_for_user(token2)
  88. # But the third should fail
  89. with self.assertRaises(SynapseError) as cm:
  90. self.do_sync_for_user(token3)
  91. e = cm.exception
  92. self.assertEqual(e.code, 403)
  93. self.assertEqual(e.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
  94. # And new registrations are now denied too
  95. with self.assertRaises(SynapseError) as cm:
  96. self.create_user("kermit4")
  97. e = cm.exception
  98. self.assertEqual(e.code, 403)
  99. self.assertEqual(e.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
  100. @override_config({"mau_trial_days": 1})
  101. def test_trial_users_cant_come_back(self):
  102. self.hs.config.mau_trial_days = 1
  103. # We should be able to register more than the limit initially
  104. token1 = self.create_user("kermit1")
  105. self.do_sync_for_user(token1)
  106. token2 = self.create_user("kermit2")
  107. self.do_sync_for_user(token2)
  108. token3 = self.create_user("kermit3")
  109. self.do_sync_for_user(token3)
  110. # Advance time by 2 days
  111. self.reactor.advance(2 * 24 * 60 * 60)
  112. # Two users should be able to sync
  113. self.do_sync_for_user(token1)
  114. self.do_sync_for_user(token2)
  115. # Advance by 2 months so everyone falls out of MAU
  116. self.reactor.advance(60 * 24 * 60 * 60)
  117. self.store.reap_monthly_active_users()
  118. self.reactor.advance(0)
  119. # We can create as many new users as we want
  120. token4 = self.create_user("kermit4")
  121. self.do_sync_for_user(token4)
  122. token5 = self.create_user("kermit5")
  123. self.do_sync_for_user(token5)
  124. token6 = self.create_user("kermit6")
  125. self.do_sync_for_user(token6)
  126. # users 2 and 3 can come back to bring us back up to MAU limit
  127. self.do_sync_for_user(token2)
  128. self.do_sync_for_user(token3)
  129. # New trial users can still sync
  130. self.do_sync_for_user(token4)
  131. self.do_sync_for_user(token5)
  132. self.do_sync_for_user(token6)
  133. # But old user cant
  134. with self.assertRaises(SynapseError) as cm:
  135. self.do_sync_for_user(token1)
  136. e = cm.exception
  137. self.assertEqual(e.code, 403)
  138. self.assertEqual(e.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
  139. @override_config(
  140. # max_mau_value should not matter
  141. {"max_mau_value": 1, "limit_usage_by_mau": False, "mau_stats_only": True}
  142. )
  143. def test_tracked_but_not_limited(self):
  144. # Simply being able to create 2 users indicates that the
  145. # limit was not reached.
  146. token1 = self.create_user("kermit1")
  147. self.do_sync_for_user(token1)
  148. token2 = self.create_user("kermit2")
  149. self.do_sync_for_user(token2)
  150. # We do want to verify that the number of tracked users
  151. # matches what we want though
  152. count = self.store.get_monthly_active_count()
  153. self.reactor.advance(100)
  154. self.assertEqual(2, self.successResultOf(count))
  155. def create_user(self, localpart):
  156. request_data = json.dumps(
  157. {
  158. "username": localpart,
  159. "password": "monkey",
  160. "auth": {"type": LoginType.DUMMY},
  161. }
  162. )
  163. request, channel = self.make_request("POST", "/register", request_data)
  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()
  169. access_token = channel.json_body["access_token"]
  170. return access_token
  171. def do_sync_for_user(self, token):
  172. request, channel = self.make_request("GET", "/sync", access_token=token)
  173. self.render(request)
  174. if channel.code != 200:
  175. raise HttpResponseException(
  176. channel.code, channel.result["reason"], channel.result["body"]
  177. ).to_synapse_error()