From a97cec18bba42e5cb743f61e79f253d6d95a0c0c Mon Sep 17 00:00:00 2001
From: Hubert Chathi <hubert@uhoreg.ca>
Date: Thu, 8 Oct 2020 13:24:46 -0400
Subject: [PATCH] Invalidate the cache when an olm fallback key is uploaded
 (#8501)

---
 changelog.d/8501.feature                      |  1 +
 .../storage/databases/main/end_to_end_keys.py |  4 ++++
 tests/handlers/test_e2e_keys.py               | 20 +++++++++++++++++++
 3 files changed, 25 insertions(+)
 create mode 100644 changelog.d/8501.feature

diff --git a/changelog.d/8501.feature b/changelog.d/8501.feature
new file mode 100644
index 0000000000..5220ddd482
--- /dev/null
+++ b/changelog.d/8501.feature
@@ -0,0 +1 @@
+Add support for olm fallback keys ([MSC2732](https://github.com/matrix-org/matrix-doc/pull/2732)).
diff --git a/synapse/storage/databases/main/end_to_end_keys.py b/synapse/storage/databases/main/end_to_end_keys.py
index 359dc6e968..4415909414 100644
--- a/synapse/storage/databases/main/end_to_end_keys.py
+++ b/synapse/storage/databases/main/end_to_end_keys.py
@@ -398,6 +398,10 @@ class EndToEndKeyWorkerStore(SQLBaseStore):
                 desc="set_e2e_fallback_key",
             )
 
+        await self.invalidate_cache_and_stream(
+            "get_e2e_unused_fallback_key_types", (user_id, device_id)
+        )
+
     @cached(max_entries=10000)
     async def get_e2e_unused_fallback_key_types(
         self, user_id: str, device_id: str
diff --git a/tests/handlers/test_e2e_keys.py b/tests/handlers/test_e2e_keys.py
index 4e9e3dcbc2..e79d612f7a 100644
--- a/tests/handlers/test_e2e_keys.py
+++ b/tests/handlers/test_e2e_keys.py
@@ -33,6 +33,7 @@ class E2eKeysHandlerTestCase(unittest.TestCase):
         super().__init__(*args, **kwargs)
         self.hs = None  # type: synapse.server.HomeServer
         self.handler = None  # type: synapse.handlers.e2e_keys.E2eKeysHandler
+        self.store = None  # type: synapse.storage.Storage
 
     @defer.inlineCallbacks
     def setUp(self):
@@ -40,6 +41,7 @@ class E2eKeysHandlerTestCase(unittest.TestCase):
             self.addCleanup, handlers=None, federation_client=mock.Mock()
         )
         self.handler = synapse.handlers.e2e_keys.E2eKeysHandler(self.hs)
+        self.store = self.hs.get_datastore()
 
     @defer.inlineCallbacks
     def test_query_local_devices_no_devices(self):
@@ -178,6 +180,12 @@ class E2eKeysHandlerTestCase(unittest.TestCase):
         fallback_key = {"alg1:k1": "key1"}
         otk = {"alg1:k2": "key2"}
 
+        # we shouldn't have any unused fallback keys yet
+        res = yield defer.ensureDeferred(
+            self.store.get_e2e_unused_fallback_key_types(local_user, device_id)
+        )
+        self.assertEqual(res, [])
+
         yield defer.ensureDeferred(
             self.handler.upload_keys_for_user(
                 local_user,
@@ -186,6 +194,12 @@ class E2eKeysHandlerTestCase(unittest.TestCase):
             )
         )
 
+        # we should now have an unused alg1 key
+        res = yield defer.ensureDeferred(
+            self.store.get_e2e_unused_fallback_key_types(local_user, device_id)
+        )
+        self.assertEqual(res, ["alg1"])
+
         # claiming an OTK when no OTKs are available should return the fallback
         # key
         res = yield defer.ensureDeferred(
@@ -198,6 +212,12 @@ class E2eKeysHandlerTestCase(unittest.TestCase):
             {"failures": {}, "one_time_keys": {local_user: {device_id: fallback_key}}},
         )
 
+        # we shouldn't have any unused fallback keys again
+        res = yield defer.ensureDeferred(
+            self.store.get_e2e_unused_fallback_key_types(local_user, device_id)
+        )
+        self.assertEqual(res, [])
+
         # claiming an OTK again should return the same fallback key
         res = yield defer.ensureDeferred(
             self.handler.claim_one_time_keys(
-- 
GitLab