test_mau.py 7.4 KB

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