forked from mystiq/hydrogen-web
wire up the olm decryption,megolm room key handler and to_device handler
This commit is contained in:
parent
0219932f50
commit
7d517eb700
2 changed files with 49 additions and 9 deletions
|
@ -19,12 +19,15 @@ import { ObservableMap } from "../observable/index.js";
|
||||||
import { SendScheduler, RateLimitingBackoff } from "./SendScheduler.js";
|
import { SendScheduler, RateLimitingBackoff } from "./SendScheduler.js";
|
||||||
import {User} from "./User.js";
|
import {User} from "./User.js";
|
||||||
import {Account as E2EEAccount} from "./e2ee/Account.js";
|
import {Account as E2EEAccount} from "./e2ee/Account.js";
|
||||||
|
import {DeviceMessageHandler} from "./DeviceMessageHandler.js";
|
||||||
|
import {Decryption as OlmDecryption} from "./e2ee/olm/Decryption.js";
|
||||||
|
import {Decryption as MegOlmDecryption} from "./e2ee/megolm/Decryption.js";
|
||||||
import {DeviceTracker} from "./e2ee/DeviceTracker.js";
|
import {DeviceTracker} from "./e2ee/DeviceTracker.js";
|
||||||
const PICKLE_KEY = "DEFAULT_KEY";
|
const PICKLE_KEY = "DEFAULT_KEY";
|
||||||
|
|
||||||
export class Session {
|
export class Session {
|
||||||
// sessionInfo contains deviceId, userId and homeServer
|
// sessionInfo contains deviceId, userId and homeServer
|
||||||
constructor({storage, hsApi, sessionInfo, olm}) {
|
constructor({storage, hsApi, sessionInfo, olm, clock}) {
|
||||||
this._storage = storage;
|
this._storage = storage;
|
||||||
this._hsApi = hsApi;
|
this._hsApi = hsApi;
|
||||||
this._syncInfo = null;
|
this._syncInfo = null;
|
||||||
|
@ -33,16 +36,38 @@ export class Session {
|
||||||
this._sendScheduler = new SendScheduler({hsApi, backoff: new RateLimitingBackoff()});
|
this._sendScheduler = new SendScheduler({hsApi, backoff: new RateLimitingBackoff()});
|
||||||
this._roomUpdateCallback = (room, params) => this._rooms.update(room.id, params);
|
this._roomUpdateCallback = (room, params) => this._rooms.update(room.id, params);
|
||||||
this._user = new User(sessionInfo.userId);
|
this._user = new User(sessionInfo.userId);
|
||||||
|
this._clock = clock;
|
||||||
this._olm = olm;
|
this._olm = olm;
|
||||||
|
this._olmUtil = null;
|
||||||
this._e2eeAccount = null;
|
this._e2eeAccount = null;
|
||||||
const olmUtil = olm ? new olm.Utility() : null;
|
this._deviceTracker = null;
|
||||||
this._deviceTracker = olm ? new DeviceTracker({
|
this._olmDecryption = null;
|
||||||
|
this._deviceMessageHandler = new DeviceMessageHandler({storage});
|
||||||
|
if (olm) {
|
||||||
|
this._olmUtil = new olm.Utility();
|
||||||
|
this._deviceTracker = new DeviceTracker({
|
||||||
storage,
|
storage,
|
||||||
getSyncToken: () => this.syncToken,
|
getSyncToken: () => this.syncToken,
|
||||||
olmUtil,
|
olmUtil: this._olmUtil,
|
||||||
}) : null;
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// called once this._e2eeAccount is assigned
|
||||||
|
_setupEncryption() {
|
||||||
|
const olmDecryption = new OlmDecryption({
|
||||||
|
account: this._e2eeAccount,
|
||||||
|
pickleKey: PICKLE_KEY,
|
||||||
|
now: this._clock.now,
|
||||||
|
ownUserId: this._user.id,
|
||||||
|
storage: this._storage,
|
||||||
|
olm: this._olm,
|
||||||
|
});
|
||||||
|
const megolmDecryption = new MegOlmDecryption({pickleKey: PICKLE_KEY});
|
||||||
|
this._deviceMessageHandler.enableEncryption({olmDecryption, megolmDecryption});
|
||||||
|
}
|
||||||
|
|
||||||
|
// called after load
|
||||||
async beforeFirstSync(isNewLogin) {
|
async beforeFirstSync(isNewLogin) {
|
||||||
if (this._olm) {
|
if (this._olm) {
|
||||||
if (isNewLogin && this._e2eeAccount) {
|
if (isNewLogin && this._e2eeAccount) {
|
||||||
|
@ -66,9 +91,11 @@ export class Session {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
await txn.complete();
|
await txn.complete();
|
||||||
|
this._setupEncryption();
|
||||||
}
|
}
|
||||||
await this._e2eeAccount.generateOTKsIfNeeded(this._storage);
|
await this._e2eeAccount.generateOTKsIfNeeded(this._storage);
|
||||||
await this._e2eeAccount.uploadKeys(this._storage);
|
await this._e2eeAccount.uploadKeys(this._storage);
|
||||||
|
await this._deviceMessageHandler.decryptPending();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +120,9 @@ export class Session {
|
||||||
deviceId: this._sessionInfo.deviceId,
|
deviceId: this._sessionInfo.deviceId,
|
||||||
txn
|
txn
|
||||||
});
|
});
|
||||||
|
if (this._e2eeAccount) {
|
||||||
|
this._setupEncryption();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const pendingEventsByRoomId = await this._getPendingEventsByRoom(txn);
|
const pendingEventsByRoomId = await this._getPendingEventsByRoom(txn);
|
||||||
// load rooms
|
// load rooms
|
||||||
|
@ -175,6 +205,7 @@ export class Session {
|
||||||
}
|
}
|
||||||
if (this._deviceTracker) {
|
if (this._deviceTracker) {
|
||||||
for (const {room, changes} of roomChanges) {
|
for (const {room, changes} of roomChanges) {
|
||||||
|
// TODO: move this so the room passes this to it's "encryption" object in its own writeSync method?
|
||||||
if (room.isTrackingMembers && changes.memberChanges?.size) {
|
if (room.isTrackingMembers && changes.memberChanges?.size) {
|
||||||
await this._deviceTracker.writeMemberChanges(room, changes.memberChanges, txn);
|
await this._deviceTracker.writeMemberChanges(room, changes.memberChanges, txn);
|
||||||
}
|
}
|
||||||
|
@ -184,6 +215,11 @@ export class Session {
|
||||||
await this._deviceTracker.writeDeviceChanges(deviceLists, txn);
|
await this._deviceTracker.writeDeviceChanges(deviceLists, txn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const toDeviceEvents = syncResponse.to_device?.events;
|
||||||
|
if (Array.isArray(toDeviceEvents)) {
|
||||||
|
this._deviceMessageHandler.writeSync(toDeviceEvents, txn);
|
||||||
|
}
|
||||||
return changes;
|
return changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,11 +235,14 @@ export class Session {
|
||||||
|
|
||||||
async afterSyncCompleted() {
|
async afterSyncCompleted() {
|
||||||
const needsToUploadOTKs = await this._e2eeAccount.generateOTKsIfNeeded(this._storage);
|
const needsToUploadOTKs = await this._e2eeAccount.generateOTKsIfNeeded(this._storage);
|
||||||
|
const promises = [this._deviceMessageHandler.decryptPending()];
|
||||||
if (needsToUploadOTKs) {
|
if (needsToUploadOTKs) {
|
||||||
// TODO: we could do this in parallel with sync if it proves to be too slow
|
// TODO: we could do this in parallel with sync if it proves to be too slow
|
||||||
// but I'm not sure how to not swallow errors in that case
|
// but I'm not sure how to not swallow errors in that case
|
||||||
await this._e2eeAccount.uploadKeys(this._storage);
|
promises.push(this._e2eeAccount.uploadKeys(this._storage));
|
||||||
}
|
}
|
||||||
|
// run key upload and decryption in parallel
|
||||||
|
await Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
get syncToken() {
|
get syncToken() {
|
||||||
|
|
|
@ -151,7 +151,8 @@ export class SessionContainer {
|
||||||
homeServer: sessionInfo.homeServer,
|
homeServer: sessionInfo.homeServer,
|
||||||
};
|
};
|
||||||
const olm = await this._olmPromise;
|
const olm = await this._olmPromise;
|
||||||
this._session = new Session({storage: this._storage, sessionInfo: filteredSessionInfo, hsApi, olm});
|
this._session = new Session({storage: this._storage,
|
||||||
|
sessionInfo: filteredSessionInfo, hsApi, olm, clock: this._clock});
|
||||||
await this._session.load();
|
await this._session.load();
|
||||||
await this._session.beforeFirstSync(isNewLogin);
|
await this._session.beforeFirstSync(isNewLogin);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue