Skip to content

Commit c05eeb9

Browse files
TinyOlm --> indexDb support complete.
1 parent 34f857a commit c05eeb9

File tree

4 files changed

+171
-44
lines changed

4 files changed

+171
-44
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "tiny-crypto-suite",
3-
"version": "1.4.1",
3+
"version": "1.4.2",
44
"description": "Tiny tools, big crypto — seamless encryption and certificate handling for modern web and Node apps.",
55
"scripts": {
66
"test": "npm run test:mjs && npm run test:cjs && npm run test:js",

src/TinyOlm/Events.mjs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,25 @@
33
* Each key maps to its string identifier.
44
*/
55
class TinyOlmEvents {
6+
/**
7+
* This class is not meant to be instantiated.
8+
*
9+
* TinyOlmEvents is a static-only class. All its members should be accessed directly through the class.
10+
*
11+
* @throws {Error} Always throws an error saying you can't summon it like a tiny pudding.
12+
*/
13+
constructor() {
14+
throw new Error(
15+
"Oops! TinyOlmEvents isn't something you can summon like a tiny pudding. Just use it statically~ 🍮",
16+
);
17+
}
18+
619
/** Emits when a value needs to be stored in the database */
720
static DbPut = 'DbPut';
21+
/** Emits when a value needs to be deleted in the database */
22+
static DbDelete = 'DbDelete';
23+
/** Emits when a entire table list needs to be deleted in the database */
24+
static DbClear = 'DbClear';
825

926
/** Sets the user's password */
1027
static SetPassword = 'SetPassword';

src/TinyOlm/Instance.mjs

Lines changed: 136 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -210,36 +210,88 @@ class TinyOlmInstance {
210210
#watchForPickleChanges() {
211211
this.#dbEvents.setMaxListeners(1000);
212212

213-
this.#dbEvents.on(TinyOlmEvents.SetPassword, () => {});
214-
this.#dbEvents.on(TinyOlmEvents.SetUserId, () => {});
215-
this.#dbEvents.on(TinyOlmEvents.SetDeviceId, () => {});
216-
217-
this.#dbEvents.on(TinyOlmEvents.ImportAccount, () => {});
218-
this.#dbEvents.on(TinyOlmEvents.ImportSession, () => {});
219-
this.#dbEvents.on(TinyOlmEvents.ImportGroupSession, () => {});
220-
this.#dbEvents.on(TinyOlmEvents.ImportInboundGroupSession, () => {});
221-
this.#dbEvents.on(TinyOlmEvents.ImportGroupSessionId, () => {});
222-
223-
this.#dbEvents.on(TinyOlmEvents.RemoveSession, () => {});
224-
this.#dbEvents.on(TinyOlmEvents.RemoveGroupSession, () => {});
225-
this.#dbEvents.on(TinyOlmEvents.RemoveInboundGroupSession, () => {});
226-
227-
this.#dbEvents.on(TinyOlmEvents.ClearSessions, () => {});
228-
this.#dbEvents.on(TinyOlmEvents.ClearInboundGroupSessions, () => {});
229-
this.#dbEvents.on(TinyOlmEvents.ClearGroupSessions, () => {});
230-
231-
this.#dbEvents.on(TinyOlmEvents.CreateAccount, () => {});
232-
this.#dbEvents.on(TinyOlmEvents.CreateGroupSession, () => {});
233-
this.#dbEvents.on(TinyOlmEvents.CreateInboundSession, () => {});
234-
this.#dbEvents.on(TinyOlmEvents.CreateOutboundSession, () => {});
235-
236-
this.#dbEvents.on(TinyOlmEvents.SignOneTimeKeys, () => {});
237-
this.#dbEvents.on(TinyOlmEvents.MarkKeysAsPublished, () => {});
238-
239-
this.#dbEvents.on(TinyOlmEvents.ResetAccount, () => {});
213+
const saveAccount = () => {
214+
if (this.account) this.#idbPut('account', 'main', this.account.pickle(this.password));
215+
};
240216

241-
// this.#idbPut('account', 'main', this.getAccountPickle());
242-
// this.#idbPut('sessions', userId, this.getSessionPickle(userId));
217+
this.#dbEvents.on(TinyOlmEvents.SetPassword, () =>
218+
this.#idbPut('account', 'password', this.password),
219+
);
220+
this.#dbEvents.on(TinyOlmEvents.SetUserId, () =>
221+
this.#idbPut('account', 'userId', this.userId),
222+
);
223+
this.#dbEvents.on(TinyOlmEvents.SetDeviceId, () =>
224+
this.#idbPut('account', 'deviceId', this.deviceId),
225+
);
226+
227+
this.#idbPut('account', 'password', this.password);
228+
this.#idbPut('account', 'userId', this.userId);
229+
this.#idbPut('account', 'deviceId', this.deviceId);
230+
231+
this.#dbEvents.on(TinyOlmEvents.SignOneTimeKeys, () => saveAccount());
232+
this.#dbEvents.on(TinyOlmEvents.MarkKeysAsPublished, () => saveAccount());
233+
234+
this.#dbEvents.on(
235+
TinyOlmEvents.ImportAccount,
236+
/** @param {Olm.Account} account */
237+
(account) => this.#idbPut('account', 'main', account.pickle(this.password)),
238+
);
239+
this.#dbEvents.on(
240+
TinyOlmEvents.ImportSession,
241+
/** @param {Olm.Session} session */
242+
(key, session) => this.#idbPut('sessions', key, session.pickle(this.password)),
243+
);
244+
this.#dbEvents.on(
245+
TinyOlmEvents.ImportGroupSession,
246+
/** @param {Olm.OutboundGroupSession} session */
247+
(key, session) => this.#idbPut('groupSessions', key, session.pickle(this.password)),
248+
);
249+
this.#dbEvents.on(
250+
TinyOlmEvents.ImportInboundGroupSession,
251+
/** @param {Olm.InboundGroupSession} session */
252+
(key, session) => this.#idbPut('groupInboundSessions', key, session.pickle(this.password)),
253+
);
254+
this.#dbEvents.on(
255+
TinyOlmEvents.ImportGroupSessionId,
256+
/** @param {Olm.InboundGroupSession} session */
257+
(key, session) => this.#idbPut('groupInboundSessions', key, session.pickle(this.password)),
258+
);
259+
260+
this.#dbEvents.on(TinyOlmEvents.RemoveSession, (key) => this.#idbDelete('sessions', key));
261+
this.#dbEvents.on(TinyOlmEvents.RemoveGroupSession, (key) =>
262+
this.#idbDelete('groupSessions', key),
263+
);
264+
this.#dbEvents.on(TinyOlmEvents.RemoveInboundGroupSession, (key) =>
265+
this.#idbDelete('groupInboundSessions', key),
266+
);
267+
this.#dbEvents.on(TinyOlmEvents.ResetAccount, () => this.#idbDelete('account', 'main'));
268+
269+
this.#dbEvents.on(TinyOlmEvents.ClearSessions, () => this.#idbClear('sessions'));
270+
this.#dbEvents.on(TinyOlmEvents.ClearInboundGroupSessions, () =>
271+
this.#idbClear('groupInboundSessions'),
272+
);
273+
this.#dbEvents.on(TinyOlmEvents.ClearGroupSessions, () => this.#idbClear('groupSessions'));
274+
275+
this.#dbEvents.on(
276+
TinyOlmEvents.CreateAccount,
277+
/** @param {Olm.Account} account */ (account) =>
278+
this.#idbPut('account', 'main', account.pickle(this.password)),
279+
);
280+
this.#dbEvents.on(
281+
TinyOlmEvents.CreateGroupSession,
282+
/** @param {Olm.OutboundGroupSession} session */
283+
(key, session) => this.#idbPut('groupSessions', key, session.pickle(this.password)),
284+
);
285+
this.#dbEvents.on(
286+
TinyOlmEvents.CreateInboundSession,
287+
/** @param {Olm.Session} session */
288+
(key, session) => this.#idbPut('sessions', key, session.pickle(this.password)),
289+
);
290+
this.#dbEvents.on(
291+
TinyOlmEvents.CreateOutboundSession,
292+
/** @param {Olm.Session} session */
293+
(key, session) => this.#idbPut('sessions', key, session.pickle(this.password)),
294+
);
243295
}
244296

245297
/**
@@ -307,6 +359,47 @@ class TinyOlmInstance {
307359
});
308360
}
309361

362+
/**
363+
* Deletes a value from the specified IndexedDB store.
364+
*
365+
* @param {string} store - The store name.
366+
* @param {IDBValidKey} key - The key to delete.
367+
* @returns {Promise<void>}
368+
*/
369+
#idbDelete(store, key) {
370+
return this.#queue.enqueue(() => {
371+
const tx = this.getDb().transaction([store], 'readwrite');
372+
const req = tx.objectStore(store).delete(key);
373+
return new Promise((resolve, reject) => {
374+
req.onsuccess = () => {
375+
this.#events.emit(TinyOlmEvents.DbDelete, store, key);
376+
resolve(req.result);
377+
};
378+
req.onerror = () => reject(req.error);
379+
});
380+
});
381+
}
382+
383+
/**
384+
* Clears all values from the specified IndexedDB store.
385+
*
386+
* @param {string} store - The store name.
387+
* @returns {Promise<void>}
388+
*/
389+
#idbClear(store) {
390+
return this.#queue.enqueue(() => {
391+
const tx = this.getDb().transaction([store], 'readwrite');
392+
const req = tx.objectStore(store).clear();
393+
return new Promise((resolve, reject) => {
394+
req.onsuccess = () => {
395+
this.#events.emit(TinyOlmEvents.DbClear, store);
396+
resolve(req.result);
397+
};
398+
req.onerror = () => reject(req.error);
399+
});
400+
});
401+
}
402+
310403
/**
311404
* Returns the name of the current IndexedDB database.
312405
*
@@ -394,8 +487,8 @@ class TinyOlmInstance {
394487
}
395488

396489
async _testIndexDb() {
397-
const accountPickle = await this.#idbGet('account', 'main');
398-
console.log(accountPickle);
490+
const accountPickles = await this.#idbGetAll('account');
491+
console.log(accountPickles);
399492

400493
const sessionPickles = await this.#idbGetAll('sessions');
401494
console.log(sessionPickles);
@@ -606,7 +699,7 @@ class TinyOlmInstance {
606699
const sess = new Olm.Session();
607700
sess.unpickle(password, pickled);
608701
this.sessions.set(key, sess);
609-
this.#emit(TinyOlmEvents.ImportSession, sess);
702+
this.#emit(TinyOlmEvents.ImportSession, key, sess);
610703
}
611704

612705
/**
@@ -622,7 +715,7 @@ class TinyOlmInstance {
622715
const group = new Olm.OutboundGroupSession();
623716
group.unpickle(password, pickled);
624717
this.groupSessions.set(key, group);
625-
this.#emit(TinyOlmEvents.ImportGroupSession, group);
718+
this.#emit(TinyOlmEvents.ImportGroupSession, key, group);
626719
}
627720

628721
/**
@@ -638,7 +731,7 @@ class TinyOlmInstance {
638731
const inbound = new Olm.InboundGroupSession();
639732
inbound.unpickle(password, pickled);
640733
this.groupInboundSessions.set(key, inbound);
641-
this.#emit(TinyOlmEvents.ImportInboundGroupSession, inbound);
734+
this.#emit(TinyOlmEvents.ImportInboundGroupSession, key, inbound);
642735
}
643736

644737
/**
@@ -695,7 +788,7 @@ class TinyOlmInstance {
695788
removeSession(userId) {
696789
const session = this.getSession(userId);
697790
session.free();
698-
this.#emit(TinyOlmEvents.RemoveSession, session);
791+
this.#emit(TinyOlmEvents.RemoveSession, userId, session);
699792
return this.sessions.delete(userId);
700793
}
701794

@@ -742,7 +835,7 @@ class TinyOlmInstance {
742835
const outboundSession = new Olm.OutboundGroupSession();
743836
outboundSession.create();
744837
this.groupSessions.set(roomId, outboundSession);
745-
this.#emit(TinyOlmEvents.CreateGroupSession, outboundSession);
838+
this.#emit(TinyOlmEvents.CreateGroupSession, roomId, outboundSession);
746839
return outboundSession;
747840
}
748841

@@ -769,8 +862,9 @@ class TinyOlmInstance {
769862
const Olm = tinyOlm.getOlm();
770863
const inboundSession = new Olm.InboundGroupSession();
771864
inboundSession.create(sessionKey);
772-
this.groupInboundSessions.set(this.#getGroupSessionId(roomId, userId), inboundSession);
773-
this.#emit(TinyOlmEvents.ImportGroupSessionId, inboundSession);
865+
const sessionId = this.#getGroupSessionId(roomId, userId);
866+
this.groupInboundSessions.set(sessionId, inboundSession);
867+
this.#emit(TinyOlmEvents.ImportGroupSessionId, sessionId, inboundSession);
774868
}
775869

776870
/**
@@ -801,7 +895,7 @@ class TinyOlmInstance {
801895
removeGroupSession(roomId) {
802896
const session = this.getGroupSession(roomId);
803897
session.free();
804-
this.#emit(TinyOlmEvents.RemoveGroupSession, session);
898+
this.#emit(TinyOlmEvents.RemoveGroupSession, roomId, session);
805899
return this.groupSessions.delete(roomId);
806900
}
807901

@@ -849,7 +943,7 @@ class TinyOlmInstance {
849943
const sessionId = this.#getGroupSessionId(roomId, userId);
850944
const session = this.getInboundGroupSession(sessionId);
851945
session.free();
852-
this.#emit(TinyOlmEvents.RemoveInboundGroupSession, session);
946+
this.#emit(TinyOlmEvents.RemoveInboundGroupSession, sessionId, session);
853947
return this.groupInboundSessions.delete(sessionId);
854948
}
855949

@@ -1049,7 +1143,7 @@ class TinyOlmInstance {
10491143
const session = new Olm.Session();
10501144
session.create_outbound(this.account, theirIdentityKey, theirOneTimeKey);
10511145
this.sessions.set(theirUsername, session);
1052-
this.#emit(TinyOlmEvents.CreateOutboundSession, session);
1146+
this.#emit(TinyOlmEvents.CreateOutboundSession, theirUsername, session);
10531147
}
10541148

10551149
/**
@@ -1068,7 +1162,7 @@ class TinyOlmInstance {
10681162
session.create_inbound_from(this.account, senderIdentityKey, ciphertext);
10691163
this.account.remove_one_time_keys(session);
10701164
this.sessions.set(senderUsername, session);
1071-
this.#emit(TinyOlmEvents.CreateInboundSession, session);
1165+
this.#emit(TinyOlmEvents.CreateInboundSession, senderUsername, session);
10721166
}
10731167

10741168
/**

test/TinyOlm.mjs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,13 @@ async function simulateSingleMatrixCommunication() {
245245

246246
console.log(divider());
247247

248-
await alice._testIndexDb();
248+
await new Promise((resolve) =>
249+
setTimeout(async () => {
250+
await alice._testIndexDb();
251+
resolve();
252+
}, 200),
253+
);
254+
249255
console.log(header('Conversation Ended ✅'));
250256
}
251257

@@ -265,6 +271,7 @@ async function simulateGroupMatrixCommunication() {
265271
console.log(header('Initializing Accounts 🚀'));
266272

267273
await Promise.all([alice.init(), bob.init(), charlie.init(), diana.init()]);
274+
await alice.initIndexDb();
268275

269276
console.log(header('Generating & Uploading Keys 🔑'));
270277

@@ -425,6 +432,15 @@ async function simulateGroupMatrixCommunication() {
425432

426433
console.log(divider());
427434

435+
await new Promise((resolve) =>
436+
setTimeout(async () => {
437+
await alice._testIndexDb();
438+
resolve();
439+
}, 200),
440+
);
441+
442+
console.log(divider());
443+
428444
// Alice, Bob, and Charlie decrypt Diana's content
429445
for (const [user, tag] of [
430446
[alice, aliceTag],

0 commit comments

Comments
 (0)