1// Copyright 2024 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
1415//! Schema-only migrations adding various stores and indices, notably
16//! the first version of `inbound_group_sessions`.
1718use indexed_db_futures::IdbDatabase;
19use web_sys::DomException;
2021use crate::crypto_store::{
22 keys,
23 migrations::{add_nonunique_index, add_unique_index, do_schema_upgrade, old_keys},
24Result,
25};
2627/// Perform schema migrations as needed, up to schema version 5.
28pub(crate) async fn schema_add(name: &str) -> Result<(), DomException> {
29 do_schema_upgrade(name, 5, |db, _, old_version| {
30// An old_version of 1 could either mean actually the first version of the
31 // schema, or a completely empty schema that has been created with a
32 // call to `IdbDatabase::open` with no explicit "version". So, to determine
33 // if we need to create the V1 stores, we actually check if the schema is empty.
34if db.object_store_names().next().is_none() {
35 schema_add_v1(db)?;
36 }
3738if old_version < 2 {
39 schema_add_v2(db)?;
40 }
4142if old_version < 3 {
43 schema_add_v3(db)?;
44 }
4546if old_version < 4 {
47 schema_add_v4(db)?;
48 }
4950if old_version < 5 {
51 schema_add_v5(db)?;
52 }
5354Ok(())
55 })
56 .await
57}
5859fn schema_add_v1(db: &IdbDatabase) -> Result<(), DomException> {
60 db.create_object_store(keys::CORE)?;
61 db.create_object_store(keys::SESSION)?;
6263 db.create_object_store(old_keys::INBOUND_GROUP_SESSIONS_V1)?;
64 db.create_object_store(keys::OUTBOUND_GROUP_SESSIONS)?;
65 db.create_object_store(keys::TRACKED_USERS)?;
66 db.create_object_store(keys::OLM_HASHES)?;
67 db.create_object_store(keys::DEVICES)?;
6869 db.create_object_store(keys::IDENTITIES)?;
70 db.create_object_store(keys::BACKUP_KEYS)?;
7172Ok(())
73}
7475fn schema_add_v2(db: &IdbDatabase) -> Result<(), DomException> {
76// We changed how we store inbound group sessions, the key used to
77 // be a tuple of `(room_id, sender_key, session_id)` now it's a
78 // tuple of `(room_id, session_id)`
79 //
80 // Let's just drop the whole object store.
81db.delete_object_store(old_keys::INBOUND_GROUP_SESSIONS_V1)?;
82 db.create_object_store(old_keys::INBOUND_GROUP_SESSIONS_V1)?;
8384 db.create_object_store(keys::ROOM_SETTINGS)?;
8586Ok(())
87}
8889fn schema_add_v3(db: &IdbDatabase) -> Result<(), DomException> {
90// We changed the way we store outbound session.
91 // ShareInfo changed from a struct to an enum with struct variant.
92 // Let's just discard the existing outbounds
93db.delete_object_store(keys::OUTBOUND_GROUP_SESSIONS)?;
94 db.create_object_store(keys::OUTBOUND_GROUP_SESSIONS)?;
9596// Support for MSC2399 withheld codes
97db.create_object_store(keys::DIRECT_WITHHELD_INFO)?;
9899Ok(())
100}
101102fn schema_add_v4(db: &IdbDatabase) -> Result<(), DomException> {
103 db.create_object_store(keys::SECRETS_INBOX)?;
104Ok(())
105}
106107fn schema_add_v5(db: &IdbDatabase) -> Result<(), DomException> {
108// Create a new store for outgoing secret requests
109let object_store = db.create_object_store(keys::GOSSIP_REQUESTS)?;
110111 add_nonunique_index(&object_store, keys::GOSSIP_REQUESTS_UNSENT_INDEX, "unsent")?;
112113 add_unique_index(&object_store, keys::GOSSIP_REQUESTS_BY_INFO_INDEX, "info")?;
114115if db.object_store_names().any(|n| n == "outgoing_secret_requests") {
116// Delete the old store names. We just delete any existing requests.
117db.delete_object_store("outgoing_secret_requests")?;
118 db.delete_object_store("unsent_secret_requests")?;
119 db.delete_object_store("secret_requests_by_info")?;
120 }
121122Ok(())
123}