diff --git a/src/matrix/Client.js b/src/matrix/Client.js index fabb489b..0eb9f6e0 100644 --- a/src/matrix/Client.js +++ b/src/matrix/Client.js @@ -151,10 +151,17 @@ export class Client { /** Method to start client after registration or with given access token. * To start the client after registering, use `startWithAuthData(registration.authData)`. * `homeserver` won't be resolved or normalized using this method, - * use `lookupHomeserver` first if needed (not needed after registration) */ - async startWithAuthData({accessToken, deviceId, userId, homeserver}) { + * use `lookupHomeserver` first if needed (not needed after registration) + * + * Setting isReadOnly to false disables OTK uploads. + * Only do this if you're sure that you will never send encrypted messages. + * */ + async startWithAuthData({accessToken, deviceId, userId, homeserver, isReadOnly = false}) { await this._platform.logger.run("startWithAuthData", async (log) => { - await this._createSessionAfterAuth({accessToken, deviceId, userId, homeserver}, true, log); + if (isReadOnly) { + log.set("isReadonly (Disabled OTK Upload)", true); + } + await this._createSessionAfterAuth({accessToken, deviceId, userId, homeserver}, true, isReadOnly, log); }); } @@ -197,11 +204,11 @@ export class Client { } return; } - await this._createSessionAfterAuth(sessionInfo, inspectAccountSetup, log); + await this._createSessionAfterAuth(sessionInfo, inspectAccountSetup, false, log); }); } - async _createSessionAfterAuth({deviceId, userId, accessToken, homeserver}, inspectAccountSetup, log) { + async _createSessionAfterAuth({deviceId, userId, accessToken, homeserver}, inspectAccountSetup, isReadOnly, log) { const id = this.createNewSessionId(); const lastUsed = this._platform.clock.now(); const sessionInfo = { @@ -212,6 +219,7 @@ export class Client { homeserver, accessToken, lastUsed, + isReadOnly, }; let dehydratedDevice; if (inspectAccountSetup) { @@ -260,6 +268,7 @@ export class Client { deviceId: sessionInfo.deviceId, userId: sessionInfo.userId, homeserver: sessionInfo.homeServer, + isReadOnly: sessionInfo.isReadOnly, }; const olm = await this._olmPromise; let olmWorker = null; diff --git a/src/matrix/Session.js b/src/matrix/Session.js index 5283b2a9..3fc3b006 100644 --- a/src/matrix/Session.js +++ b/src/matrix/Session.js @@ -417,8 +417,10 @@ export class Session { log.set("keys", this._e2eeAccount.identityKeys); await this._setupEncryption(); } - await this._e2eeAccount.generateOTKsIfNeeded(this._storage, log); - await log.wrap("uploadKeys", log => this._e2eeAccount.uploadKeys(this._storage, false, log)); + if (!this._sessionInfo.isReadOnly) { + await this._e2eeAccount.generateOTKsIfNeeded(this._storage, log); + await log.wrap("uploadKeys", log => this._e2eeAccount.uploadKeys(this._storage, false, log)); + } await this._createCrossSigning(); } } @@ -828,7 +830,7 @@ export class Session { // to-device messages, to help us avoid throwing away one-time-keys that we // are about to receive messages for // (https://github.com/vector-im/riot-web/issues/2782). - if (this._e2eeAccount && !isCatchupSync) { + if (this._e2eeAccount && !isCatchupSync && !this._sessionInfo.isReadOnly) { const needsToUploadOTKs = await this._e2eeAccount.generateOTKsIfNeeded(this._storage, log); if (needsToUploadOTKs) { await log.wrap("uploadKeys", log => this._e2eeAccount.uploadKeys(this._storage, false, log)); diff --git a/src/matrix/sessioninfo/localstorage/SessionInfoStorage.ts b/src/matrix/sessioninfo/localstorage/SessionInfoStorage.ts index ebe575f6..d6596a61 100644 --- a/src/matrix/sessioninfo/localstorage/SessionInfoStorage.ts +++ b/src/matrix/sessioninfo/localstorage/SessionInfoStorage.ts @@ -22,6 +22,15 @@ interface ISessionInfo { homeServer: string; // deprecate this over time accessToken: string; lastUsed: number; + /** + * If true, then this session will not be used for sending + * encrypted messages. + * OTK uploads will be disabled when this is true. + * + * Encrypted messages can still be decrypted and key backups + * can also be restored. + */ + isReadOnly: boolean; } // todo: this should probably be in platform/types?