diff --git a/tests/handlers/test_auth.py b/tests/handlers/test_auth.py
index 1822dcf1e0..1e39fe0ec2 100644
--- a/tests/handlers/test_auth.py
+++ b/tests/handlers/test_auth.py
@@ -12,13 +12,17 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+from mock import Mock
import pymacaroons
+
from twisted.internet import defer
import synapse
import synapse.api.errors
+from synapse.api.errors import ResourceLimitError
from synapse.handlers.auth import AuthHandler
+
from tests import unittest
from tests.utils import setup_test_homeserver
@@ -31,10 +35,14 @@ class AuthHandlers(object):
class AuthTestCase(unittest.TestCase):
@defer.inlineCallbacks
def setUp(self):
- self.hs = yield setup_test_homeserver(handlers=None)
+ self.hs = yield setup_test_homeserver(self.addCleanup, handlers=None)
self.hs.handlers = AuthHandlers(self.hs)
self.auth_handler = self.hs.handlers.auth_handler
self.macaroon_generator = self.hs.get_macaroon_generator()
+ # MAU tests
+ self.hs.config.max_mau_value = 50
+ self.small_number_of_users = 1
+ self.large_number_of_users = 100
def test_token_is_a_macaroon(self):
token = self.macaroon_generator.generate_access_token("some_user")
@@ -69,45 +77,123 @@ class AuthTestCase(unittest.TestCase):
v.satisfy_general(verify_nonce)
v.verify(macaroon, self.hs.config.macaroon_secret_key)
+ @defer.inlineCallbacks
def test_short_term_login_token_gives_user_id(self):
self.hs.clock.now = 1000
- token = self.macaroon_generator.generate_short_term_login_token(
- "a_user", 5000
- )
-
- self.assertEqual(
- "a_user",
- self.auth_handler.validate_short_term_login_token_and_get_user_id(
- token
- )
+ token = self.macaroon_generator.generate_short_term_login_token("a_user", 5000)
+ user_id = yield self.auth_handler.validate_short_term_login_token_and_get_user_id(
+ token
)
+ self.assertEqual("a_user", user_id)
# when we advance the clock, the token should be rejected
self.hs.clock.now = 6000
with self.assertRaises(synapse.api.errors.AuthError):
- self.auth_handler.validate_short_term_login_token_and_get_user_id(
+ yield self.auth_handler.validate_short_term_login_token_and_get_user_id(
token
)
+ @defer.inlineCallbacks
def test_short_term_login_token_cannot_replace_user_id(self):
- token = self.macaroon_generator.generate_short_term_login_token(
- "a_user", 5000
- )
+ token = self.macaroon_generator.generate_short_term_login_token("a_user", 5000)
macaroon = pymacaroons.Macaroon.deserialize(token)
- self.assertEqual(
- "a_user",
- self.auth_handler.validate_short_term_login_token_and_get_user_id(
- macaroon.serialize()
- )
+ user_id = yield self.auth_handler.validate_short_term_login_token_and_get_user_id(
+ macaroon.serialize()
)
+ self.assertEqual("a_user", user_id)
# add another "user_id" caveat, which might allow us to override the
# user_id.
macaroon.add_first_party_caveat("user_id = b_user")
with self.assertRaises(synapse.api.errors.AuthError):
- self.auth_handler.validate_short_term_login_token_and_get_user_id(
+ yield self.auth_handler.validate_short_term_login_token_and_get_user_id(
macaroon.serialize()
)
+
+ @defer.inlineCallbacks
+ def test_mau_limits_disabled(self):
+ self.hs.config.limit_usage_by_mau = False
+ # Ensure does not throw exception
+ yield self.auth_handler.get_access_token_for_user_id('user_a')
+
+ yield self.auth_handler.validate_short_term_login_token_and_get_user_id(
+ self._get_macaroon().serialize()
+ )
+
+ @defer.inlineCallbacks
+ def test_mau_limits_exceeded_large(self):
+ self.hs.config.limit_usage_by_mau = True
+ self.hs.get_datastore().get_monthly_active_count = Mock(
+ return_value=defer.succeed(self.large_number_of_users)
+ )
+
+ with self.assertRaises(ResourceLimitError):
+ yield self.auth_handler.get_access_token_for_user_id('user_a')
+
+ self.hs.get_datastore().get_monthly_active_count = Mock(
+ return_value=defer.succeed(self.large_number_of_users)
+ )
+ with self.assertRaises(ResourceLimitError):
+ yield self.auth_handler.validate_short_term_login_token_and_get_user_id(
+ self._get_macaroon().serialize()
+ )
+
+ @defer.inlineCallbacks
+ def test_mau_limits_parity(self):
+ self.hs.config.limit_usage_by_mau = True
+
+ # If not in monthly active cohort
+ self.hs.get_datastore().get_monthly_active_count = Mock(
+ return_value=defer.succeed(self.hs.config.max_mau_value)
+ )
+ with self.assertRaises(ResourceLimitError):
+ yield self.auth_handler.get_access_token_for_user_id('user_a')
+
+ self.hs.get_datastore().get_monthly_active_count = Mock(
+ return_value=defer.succeed(self.hs.config.max_mau_value)
+ )
+ with self.assertRaises(ResourceLimitError):
+ yield self.auth_handler.validate_short_term_login_token_and_get_user_id(
+ self._get_macaroon().serialize()
+ )
+ # If in monthly active cohort
+ self.hs.get_datastore().user_last_seen_monthly_active = Mock(
+ return_value=defer.succeed(self.hs.get_clock().time_msec())
+ )
+ self.hs.get_datastore().get_monthly_active_count = Mock(
+ return_value=defer.succeed(self.hs.config.max_mau_value)
+ )
+ yield self.auth_handler.get_access_token_for_user_id('user_a')
+ self.hs.get_datastore().user_last_seen_monthly_active = Mock(
+ return_value=defer.succeed(self.hs.get_clock().time_msec())
+ )
+ self.hs.get_datastore().get_monthly_active_count = Mock(
+ return_value=defer.succeed(self.hs.config.max_mau_value)
+ )
+ yield self.auth_handler.validate_short_term_login_token_and_get_user_id(
+ self._get_macaroon().serialize()
+ )
+
+ @defer.inlineCallbacks
+ def test_mau_limits_not_exceeded(self):
+ self.hs.config.limit_usage_by_mau = True
+
+ self.hs.get_datastore().get_monthly_active_count = Mock(
+ return_value=defer.succeed(self.small_number_of_users)
+ )
+ # Ensure does not raise exception
+ yield self.auth_handler.get_access_token_for_user_id('user_a')
+
+ self.hs.get_datastore().get_monthly_active_count = Mock(
+ return_value=defer.succeed(self.small_number_of_users)
+ )
+ yield self.auth_handler.validate_short_term_login_token_and_get_user_id(
+ self._get_macaroon().serialize()
+ )
+
+ def _get_macaroon(self):
+ token = self.macaroon_generator.generate_short_term_login_token("user_a", 5000)
+ return pymacaroons.Macaroon.deserialize(token)
|