mirror of
https://github.com/vector-im/hydrogen-web.git
synced 2024-12-23 11:35:04 +01:00
rename session backup to key backup to be consistent with RoomKey
This commit is contained in:
parent
933a1b4636
commit
86caa5f9b1
@ -16,7 +16,7 @@ limitations under the License.
|
|||||||
|
|
||||||
import {ViewModel} from "./ViewModel.js";
|
import {ViewModel} from "./ViewModel.js";
|
||||||
import {KeyType} from "../matrix/ssss/index";
|
import {KeyType} from "../matrix/ssss/index";
|
||||||
import {Status} from "./session/settings/SessionBackupViewModel.js";
|
import {Status} from "./session/settings/KeyBackupViewModel.js";
|
||||||
|
|
||||||
export class AccountSetupViewModel extends ViewModel {
|
export class AccountSetupViewModel extends ViewModel {
|
||||||
constructor(accountSetup) {
|
constructor(accountSetup) {
|
||||||
@ -50,7 +50,7 @@ export class AccountSetupViewModel extends ViewModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this vm adopts the same shape as SessionBackupViewModel so the same view can be reused.
|
// this vm adopts the same shape as KeyBackupViewModel so the same view can be reused.
|
||||||
class DecryptDehydratedDeviceViewModel extends ViewModel {
|
class DecryptDehydratedDeviceViewModel extends ViewModel {
|
||||||
constructor(accountSetupViewModel, decryptedCallback) {
|
constructor(accountSetupViewModel, decryptedCallback) {
|
||||||
super();
|
super();
|
||||||
|
@ -36,7 +36,7 @@ export class SessionStatusViewModel extends ViewModel {
|
|||||||
this._reconnector = reconnector;
|
this._reconnector = reconnector;
|
||||||
this._status = this._calculateState(reconnector.connectionStatus.get(), sync.status.get());
|
this._status = this._calculateState(reconnector.connectionStatus.get(), sync.status.get());
|
||||||
this._session = session;
|
this._session = session;
|
||||||
this._setupSessionBackupUrl = this.urlCreator.urlForSegment("settings");
|
this._setupKeyBackupUrl = this.urlCreator.urlForSegment("settings");
|
||||||
this._dismissSecretStorage = false;
|
this._dismissSecretStorage = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,17 +44,17 @@ export class SessionStatusViewModel extends ViewModel {
|
|||||||
const update = () => this._updateStatus();
|
const update = () => this._updateStatus();
|
||||||
this.track(this._sync.status.subscribe(update));
|
this.track(this._sync.status.subscribe(update));
|
||||||
this.track(this._reconnector.connectionStatus.subscribe(update));
|
this.track(this._reconnector.connectionStatus.subscribe(update));
|
||||||
this.track(this._session.needsSessionBackup.subscribe(() => {
|
this.track(this._session.needsKeyBackup.subscribe(() => {
|
||||||
this.emitChange();
|
this.emitChange();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
get setupSessionBackupUrl () {
|
get setupKeyBackupUrl () {
|
||||||
return this._setupSessionBackupUrl;
|
return this._setupKeyBackupUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isShown() {
|
get isShown() {
|
||||||
return (this._session.needsSessionBackup.get() && !this._dismissSecretStorage) || this._status !== SessionStatus.Syncing;
|
return (this._session.needsKeyBackup.get() && !this._dismissSecretStorage) || this._status !== SessionStatus.Syncing;
|
||||||
}
|
}
|
||||||
|
|
||||||
get statusLabel() {
|
get statusLabel() {
|
||||||
@ -70,7 +70,7 @@ export class SessionStatusViewModel extends ViewModel {
|
|||||||
case SessionStatus.SyncError:
|
case SessionStatus.SyncError:
|
||||||
return this.i18n`Sync failed because of ${this._sync.error}`;
|
return this.i18n`Sync failed because of ${this._sync.error}`;
|
||||||
}
|
}
|
||||||
if (this._session.needsSessionBackup.get()) {
|
if (this._session.needsKeyBackup.get()) {
|
||||||
return this.i18n`Set up session backup to decrypt older messages.`;
|
return this.i18n`Set up session backup to decrypt older messages.`;
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
@ -135,7 +135,7 @@ export class SessionStatusViewModel extends ViewModel {
|
|||||||
|
|
||||||
get isSecretStorageShown() {
|
get isSecretStorageShown() {
|
||||||
// TODO: we need a model here where we can have multiple messages queued up and their buttons don't bleed into each other.
|
// TODO: we need a model here where we can have multiple messages queued up and their buttons don't bleed into each other.
|
||||||
return this._status === SessionStatus.Syncing && this._session.needsSessionBackup.get() && !this._dismissSecretStorage;
|
return this._status === SessionStatus.Syncing && this._session.needsKeyBackup.get() && !this._dismissSecretStorage;
|
||||||
}
|
}
|
||||||
|
|
||||||
get canDismiss() {
|
get canDismiss() {
|
||||||
|
@ -20,7 +20,7 @@ import {createEnum} from "../../../utils/enum";
|
|||||||
|
|
||||||
export const Status = createEnum("Enabled", "SetupKey", "SetupPhrase", "Pending");
|
export const Status = createEnum("Enabled", "SetupKey", "SetupPhrase", "Pending");
|
||||||
|
|
||||||
export class SessionBackupViewModel extends ViewModel {
|
export class KeyBackupViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super(options);
|
super(options);
|
||||||
this._session = options.session;
|
this._session = options.session;
|
||||||
@ -43,7 +43,7 @@ export class SessionBackupViewModel extends ViewModel {
|
|||||||
let status;
|
let status;
|
||||||
const hasSecretStorageKey = this._session.hasSecretStorageKey.get();
|
const hasSecretStorageKey = this._session.hasSecretStorageKey.get();
|
||||||
if (hasSecretStorageKey === true) {
|
if (hasSecretStorageKey === true) {
|
||||||
status = this._session.sessionBackup ? Status.Enabled : Status.SetupKey;
|
status = this._session.keyBackup ? Status.Enabled : Status.SetupKey;
|
||||||
} else if (hasSecretStorageKey === false) {
|
} else if (hasSecretStorageKey === false) {
|
||||||
status = Status.SetupKey;
|
status = Status.SetupKey;
|
||||||
} else {
|
} else {
|
||||||
@ -59,7 +59,7 @@ export class SessionBackupViewModel extends ViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get purpose() {
|
get purpose() {
|
||||||
return this.i18n`set up session backup`;
|
return this.i18n`set up key backup`;
|
||||||
}
|
}
|
||||||
|
|
||||||
offerDehydratedDeviceSetup() {
|
offerDehydratedDeviceSetup() {
|
||||||
@ -75,7 +75,7 @@ export class SessionBackupViewModel extends ViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get backupVersion() {
|
get backupVersion() {
|
||||||
return this._session.sessionBackup?.version;
|
return this._session.keyBackup?.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
get status() {
|
get status() {
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {ViewModel} from "../../ViewModel.js";
|
import {ViewModel} from "../../ViewModel.js";
|
||||||
import {SessionBackupViewModel} from "./SessionBackupViewModel.js";
|
import {KeyBackupViewModel} from "./KeyBackupViewModel.js";
|
||||||
|
|
||||||
class PushNotificationStatus {
|
class PushNotificationStatus {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -43,7 +43,7 @@ export class SettingsViewModel extends ViewModel {
|
|||||||
this._updateService = options.updateService;
|
this._updateService = options.updateService;
|
||||||
const {client} = options;
|
const {client} = options;
|
||||||
this._client = client;
|
this._client = client;
|
||||||
this._sessionBackupViewModel = this.track(new SessionBackupViewModel(this.childOptions({session: this._session})));
|
this._keyBackupViewModel = this.track(new KeyBackupViewModel(this.childOptions({session: this._session})));
|
||||||
this._closeUrl = this.urlCreator.urlUntilSegment("session");
|
this._closeUrl = this.urlCreator.urlUntilSegment("session");
|
||||||
this._estimate = null;
|
this._estimate = null;
|
||||||
this.sentImageSizeLimit = null;
|
this.sentImageSizeLimit = null;
|
||||||
@ -115,8 +115,8 @@ export class SettingsViewModel extends ViewModel {
|
|||||||
return !!this.platform.updateService;
|
return !!this.platform.updateService;
|
||||||
}
|
}
|
||||||
|
|
||||||
get sessionBackupViewModel() {
|
get keyBackupViewModel() {
|
||||||
return this._sessionBackupViewModel;
|
return this._keyBackupViewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
get storageQuota() {
|
get storageQuota() {
|
||||||
|
@ -29,7 +29,7 @@ import {Decryption as OlmDecryption} from "./e2ee/olm/Decryption.js";
|
|||||||
import {Encryption as OlmEncryption} from "./e2ee/olm/Encryption.js";
|
import {Encryption as OlmEncryption} from "./e2ee/olm/Encryption.js";
|
||||||
import {Decryption as MegOlmDecryption} from "./e2ee/megolm/Decryption";
|
import {Decryption as MegOlmDecryption} from "./e2ee/megolm/Decryption";
|
||||||
import {KeyLoader as MegOlmKeyLoader} from "./e2ee/megolm/decryption/KeyLoader";
|
import {KeyLoader as MegOlmKeyLoader} from "./e2ee/megolm/decryption/KeyLoader";
|
||||||
import {SessionBackup} from "./e2ee/megolm/SessionBackup.js";
|
import {KeyBackup} from "./e2ee/megolm/keybackup/KeyBackup";
|
||||||
import {Encryption as MegOlmEncryption} from "./e2ee/megolm/Encryption.js";
|
import {Encryption as MegOlmEncryption} from "./e2ee/megolm/Encryption.js";
|
||||||
import {MEGOLM_ALGORITHM} from "./e2ee/common.js";
|
import {MEGOLM_ALGORITHM} from "./e2ee/common.js";
|
||||||
import {RoomEncryption} from "./e2ee/RoomEncryption.js";
|
import {RoomEncryption} from "./e2ee/RoomEncryption.js";
|
||||||
@ -75,7 +75,7 @@ export class Session {
|
|||||||
this._megolmDecryption = null;
|
this._megolmDecryption = null;
|
||||||
this._getSyncToken = () => this.syncToken;
|
this._getSyncToken = () => this.syncToken;
|
||||||
this._olmWorker = olmWorker;
|
this._olmWorker = olmWorker;
|
||||||
this._sessionBackup = null;
|
this._keyBackup = null;
|
||||||
this._hasSecretStorageKey = new ObservableValue(null);
|
this._hasSecretStorageKey = new ObservableValue(null);
|
||||||
this._observedRoomStatus = new Map();
|
this._observedRoomStatus = new Map();
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ export class Session {
|
|||||||
}
|
}
|
||||||
this._createRoomEncryption = this._createRoomEncryption.bind(this);
|
this._createRoomEncryption = this._createRoomEncryption.bind(this);
|
||||||
this._forgetArchivedRoom = this._forgetArchivedRoom.bind(this);
|
this._forgetArchivedRoom = this._forgetArchivedRoom.bind(this);
|
||||||
this.needsSessionBackup = new ObservableValue(false);
|
this.needsKeyBackup = new ObservableValue(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
get fingerprintKey() {
|
get fingerprintKey() {
|
||||||
@ -170,11 +170,11 @@ export class Session {
|
|||||||
megolmEncryption: this._megolmEncryption,
|
megolmEncryption: this._megolmEncryption,
|
||||||
megolmDecryption: this._megolmDecryption,
|
megolmDecryption: this._megolmDecryption,
|
||||||
storage: this._storage,
|
storage: this._storage,
|
||||||
sessionBackup: this._sessionBackup,
|
keyBackup: this._keyBackup,
|
||||||
encryptionParams,
|
encryptionParams,
|
||||||
notifyMissingMegolmSession: () => {
|
notifyMissingMegolmSession: () => {
|
||||||
if (!this._sessionBackup) {
|
if (!this._keyBackup) {
|
||||||
this.needsSessionBackup.set(true)
|
this.needsKeyBackup.set(true)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
clock: this._platform.clock
|
clock: this._platform.clock
|
||||||
@ -183,7 +183,7 @@ export class Session {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable secret storage by providing the secret storage credential.
|
* Enable secret storage by providing the secret storage credential.
|
||||||
* This will also see if there is a megolm session backup and try to enable that if so.
|
* This will also see if there is a megolm key backup and try to enable that if so.
|
||||||
*
|
*
|
||||||
* @param {string} type either "passphrase" or "recoverykey"
|
* @param {string} type either "passphrase" or "recoverykey"
|
||||||
* @param {string} credential either the passphrase or the recovery key, depending on the type
|
* @param {string} credential either the passphrase or the recovery key, depending on the type
|
||||||
@ -193,15 +193,15 @@ export class Session {
|
|||||||
if (!this._olm) {
|
if (!this._olm) {
|
||||||
throw new Error("olm required");
|
throw new Error("olm required");
|
||||||
}
|
}
|
||||||
if (this._sessionBackup) {
|
if (this._keyBackup) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const key = await ssssKeyFromCredential(type, credential, this._storage, this._platform, this._olm);
|
const key = await ssssKeyFromCredential(type, credential, this._storage, this._platform, this._olm);
|
||||||
// and create session backup, which needs to read from accountData
|
// and create key backup, which needs to read from accountData
|
||||||
const readTxn = await this._storage.readTxn([
|
const readTxn = await this._storage.readTxn([
|
||||||
this._storage.storeNames.accountData,
|
this._storage.storeNames.accountData,
|
||||||
]);
|
]);
|
||||||
await this._createSessionBackup(key, readTxn);
|
await this._createKeyBackup(key, readTxn);
|
||||||
await this._writeSSSSKey(key);
|
await this._writeSSSSKey(key);
|
||||||
this._hasSecretStorageKey.set(true);
|
this._hasSecretStorageKey.set(true);
|
||||||
return key;
|
return key;
|
||||||
@ -233,21 +233,21 @@ export class Session {
|
|||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
await writeTxn.complete();
|
await writeTxn.complete();
|
||||||
if (this._sessionBackup) {
|
if (this._keyBackup) {
|
||||||
for (const room of this._rooms.values()) {
|
for (const room of this._rooms.values()) {
|
||||||
if (room.isEncrypted) {
|
if (room.isEncrypted) {
|
||||||
room.enableSessionBackup(undefined);
|
room.enableKeyBackup(undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._sessionBackup?.dispose();
|
this._keyBackup?.dispose();
|
||||||
this._sessionBackup = undefined;
|
this._keyBackup = undefined;
|
||||||
}
|
}
|
||||||
this._hasSecretStorageKey.set(false);
|
this._hasSecretStorageKey.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _createSessionBackup(ssssKey, txn) {
|
async _createKeyBackup(ssssKey, txn) {
|
||||||
const secretStorage = new SecretStorage({key: ssssKey, platform: this._platform});
|
const secretStorage = new SecretStorage({key: ssssKey, platform: this._platform});
|
||||||
this._sessionBackup = await SessionBackup.fromSecretStorage(
|
this._keyBackup = await KeyBackup.fromSecretStorage(
|
||||||
this._platform,
|
this._platform,
|
||||||
this._olm,
|
this._olm,
|
||||||
secretStorage,
|
secretStorage,
|
||||||
@ -256,18 +256,18 @@ export class Session {
|
|||||||
this._storage,
|
this._storage,
|
||||||
txn
|
txn
|
||||||
);
|
);
|
||||||
if (this._sessionBackup) {
|
if (this._keyBackup) {
|
||||||
for (const room of this._rooms.values()) {
|
for (const room of this._rooms.values()) {
|
||||||
if (room.isEncrypted) {
|
if (room.isEncrypted) {
|
||||||
room.enableSessionBackup(this._sessionBackup);
|
room.enableKeyBackup(this._keyBackup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.needsSessionBackup.set(false);
|
this.needsKeyBackup.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
get sessionBackup() {
|
get keyBackup() {
|
||||||
return this._sessionBackup;
|
return this._keyBackup;
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasIdentity() {
|
get hasIdentity() {
|
||||||
@ -405,8 +405,8 @@ export class Session {
|
|||||||
dispose() {
|
dispose() {
|
||||||
this._olmWorker?.dispose();
|
this._olmWorker?.dispose();
|
||||||
this._olmWorker = undefined;
|
this._olmWorker = undefined;
|
||||||
this._sessionBackup?.dispose();
|
this._keyBackup?.dispose();
|
||||||
this._sessionBackup = undefined;
|
this._keyBackup = undefined;
|
||||||
this._megolmDecryption?.dispose();
|
this._megolmDecryption?.dispose();
|
||||||
this._megolmDecryption = undefined;
|
this._megolmDecryption = undefined;
|
||||||
this._e2eeAccount?.dispose();
|
this._e2eeAccount?.dispose();
|
||||||
@ -434,7 +434,7 @@ export class Session {
|
|||||||
await txn.complete();
|
await txn.complete();
|
||||||
}
|
}
|
||||||
// enable session backup, this requests the latest backup version
|
// enable session backup, this requests the latest backup version
|
||||||
if (!this._sessionBackup) {
|
if (!this._keyBackup) {
|
||||||
if (dehydratedDevice) {
|
if (dehydratedDevice) {
|
||||||
await log.wrap("SSSSKeyFromDehydratedDeviceKey", async log => {
|
await log.wrap("SSSSKeyFromDehydratedDeviceKey", async log => {
|
||||||
const ssssKey = await createSSSSKeyFromDehydratedDeviceKey(dehydratedDevice.key, this._storage, this._platform);
|
const ssssKey = await createSSSSKeyFromDehydratedDeviceKey(dehydratedDevice.key, this._storage, this._platform);
|
||||||
@ -452,7 +452,7 @@ export class Session {
|
|||||||
const ssssKey = await ssssReadKey(txn);
|
const ssssKey = await ssssReadKey(txn);
|
||||||
if (ssssKey) {
|
if (ssssKey) {
|
||||||
// txn will end here as this does a network request
|
// txn will end here as this does a network request
|
||||||
await this._createSessionBackup(ssssKey, txn);
|
await this._createKeyBackup(ssssKey, txn);
|
||||||
}
|
}
|
||||||
this._hasSecretStorageKey.set(!!ssssKey);
|
this._hasSecretStorageKey.set(!!ssssKey);
|
||||||
}
|
}
|
||||||
@ -583,8 +583,8 @@ export class Session {
|
|||||||
await log.wrap("deviceMsgs", log => this._deviceMessageHandler.writeSync(preparation, txn, log));
|
await log.wrap("deviceMsgs", log => this._deviceMessageHandler.writeSync(preparation, txn, log));
|
||||||
// this should come after the deviceMessageHandler, so the room keys are already written and their
|
// this should come after the deviceMessageHandler, so the room keys are already written and their
|
||||||
// isBetter property has been checked
|
// isBetter property has been checked
|
||||||
if (this._sessionBackup) {
|
if (this._keyBackup) {
|
||||||
this._sessionBackup.writeKeys(preparation.newRoomKeys, txn, log);
|
this._keyBackup.writeKeys(preparation.newRoomKeys, txn, log);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,8 +623,8 @@ export class Session {
|
|||||||
await log.wrap("uploadKeys", log => this._e2eeAccount.uploadKeys(this._storage, false, log));
|
await log.wrap("uploadKeys", log => this._e2eeAccount.uploadKeys(this._storage, false, log));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this._sessionBackup) {
|
if (this._keyBackup) {
|
||||||
this._sessionBackup.flush();
|
this._keyBackup.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ const MIN_PRESHARE_INTERVAL = 60 * 1000; // 1min
|
|||||||
|
|
||||||
// TODO: this class is a good candidate for splitting up into encryption and decryption, there doesn't seem to be much overlap
|
// TODO: this class is a good candidate for splitting up into encryption and decryption, there doesn't seem to be much overlap
|
||||||
export class RoomEncryption {
|
export class RoomEncryption {
|
||||||
constructor({room, deviceTracker, olmEncryption, megolmEncryption, megolmDecryption, encryptionParams, storage, sessionBackup, notifyMissingMegolmSession, clock}) {
|
constructor({room, deviceTracker, olmEncryption, megolmEncryption, megolmDecryption, encryptionParams, storage, keyBackup, notifyMissingMegolmSession, clock}) {
|
||||||
this._room = room;
|
this._room = room;
|
||||||
this._deviceTracker = deviceTracker;
|
this._deviceTracker = deviceTracker;
|
||||||
this._olmEncryption = olmEncryption;
|
this._olmEncryption = olmEncryption;
|
||||||
@ -39,7 +39,7 @@ export class RoomEncryption {
|
|||||||
// caches devices to verify events
|
// caches devices to verify events
|
||||||
this._senderDeviceCache = new Map();
|
this._senderDeviceCache = new Map();
|
||||||
this._storage = storage;
|
this._storage = storage;
|
||||||
this._sessionBackup = sessionBackup;
|
this._keyBackup = keyBackup;
|
||||||
this._notifyMissingMegolmSession = notifyMissingMegolmSession;
|
this._notifyMissingMegolmSession = notifyMissingMegolmSession;
|
||||||
this._clock = clock;
|
this._clock = clock;
|
||||||
this._isFlushingRoomKeyShares = false;
|
this._isFlushingRoomKeyShares = false;
|
||||||
@ -48,11 +48,11 @@ export class RoomEncryption {
|
|||||||
this._disposed = false;
|
this._disposed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
enableSessionBackup(sessionBackup) {
|
enableKeyBackup(keyBackup) {
|
||||||
if (this._sessionBackup && !!sessionBackup) {
|
if (this._keyBackup && !!keyBackup) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._sessionBackup = sessionBackup;
|
this._keyBackup = keyBackup;
|
||||||
}
|
}
|
||||||
|
|
||||||
async restoreMissingSessionsFromBackup(entries, log) {
|
async restoreMissingSessionsFromBackup(entries, log) {
|
||||||
@ -130,7 +130,7 @@ export class RoomEncryption {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._sessionBackup) {
|
if (!this._keyBackup) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ export class RoomEncryption {
|
|||||||
|
|
||||||
async _requestMissingSessionFromBackup(senderKey, sessionId, log) {
|
async _requestMissingSessionFromBackup(senderKey, sessionId, log) {
|
||||||
// show prompt to enable secret storage
|
// show prompt to enable secret storage
|
||||||
if (!this._sessionBackup) {
|
if (!this._keyBackup) {
|
||||||
log.set("enabled", false);
|
log.set("enabled", false);
|
||||||
this._notifyMissingMegolmSession();
|
this._notifyMissingMegolmSession();
|
||||||
return;
|
return;
|
||||||
@ -182,7 +182,7 @@ export class RoomEncryption {
|
|||||||
log.set("id", sessionId);
|
log.set("id", sessionId);
|
||||||
log.set("senderKey", senderKey);
|
log.set("senderKey", senderKey);
|
||||||
try {
|
try {
|
||||||
const roomKey = await this._sessionBackup.getRoomKey(this._room.id, sessionId, log);
|
const roomKey = await this._keyBackup.getRoomKey(this._room.id, sessionId, log);
|
||||||
if (roomKey) {
|
if (roomKey) {
|
||||||
if (roomKey.senderKey !== senderKey) {
|
if (roomKey.senderKey !== senderKey) {
|
||||||
log.set("wrong_sender_key", roomKey.senderKey);
|
log.set("wrong_sender_key", roomKey.senderKey);
|
||||||
|
@ -14,20 +14,20 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {StoreNames} from "../../storage/common";
|
import {StoreNames} from "../../../storage/common";
|
||||||
import {LRUCache} from "../../../utils/LRUCache";
|
import {LRUCache} from "../../../../utils/LRUCache";
|
||||||
import {keyFromStorage, keyFromBackup} from "./decryption/RoomKey";
|
import {keyFromStorage, keyFromBackup} from "../decryption/RoomKey";
|
||||||
import {MEGOLM_ALGORITHM} from "../common";
|
import {MEGOLM_ALGORITHM} from "../../common";
|
||||||
|
|
||||||
import type {HomeServerApi} from "../../net/HomeServerApi";
|
import type {HomeServerApi} from "../../../net/HomeServerApi";
|
||||||
import type {IncomingRoomKey, RoomKey} from "./decryption/RoomKey";
|
import type {IncomingRoomKey, RoomKey} from "../decryption/RoomKey";
|
||||||
import type {KeyLoader} from "./decryption/KeyLoader";
|
import type {KeyLoader} from "../decryption/KeyLoader";
|
||||||
import type {SecretStorage} from "../../ssss/SecretStorage";
|
import type {SecretStorage} from "../../../ssss/SecretStorage";
|
||||||
import type {Storage} from "../../storage/idb/Storage";
|
import type {Storage} from "../../../storage/idb/Storage";
|
||||||
import type {DeviceIdentity} from "../../storage/idb/stores/DeviceIdentityStore";
|
import type {DeviceIdentity} from "../../../storage/idb/stores/DeviceIdentityStore";
|
||||||
import type {ILogItem} from "../../../logging/types";
|
import type {ILogItem} from "../../../../logging/types";
|
||||||
import type {Platform} from "../../../platform/web/Platform";
|
import type {Platform} from "../../../../platform/web/Platform";
|
||||||
import type {Transaction} from "../../storage/idb/Transaction";
|
import type {Transaction} from "../../../storage/idb/Transaction";
|
||||||
import type * as OlmNamespace from "@matrix-org/olm";
|
import type * as OlmNamespace from "@matrix-org/olm";
|
||||||
type Olm = typeof OlmNamespace;
|
type Olm = typeof OlmNamespace;
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ type MegOlmSessionKeyInfo = {
|
|||||||
|
|
||||||
type SessionKeyInfo = MegOlmSessionKeyInfo | {algorithm: string};
|
type SessionKeyInfo = MegOlmSessionKeyInfo | {algorithm: string};
|
||||||
|
|
||||||
export class SessionBackup {
|
export class KeyBackup {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly backupInfo: BackupInfo,
|
private readonly backupInfo: BackupInfo,
|
||||||
private readonly algorithm: Curve25519,
|
private readonly algorithm: Curve25519,
|
||||||
@ -187,14 +187,14 @@ export class SessionBackup {
|
|||||||
this.algorithm.dispose();
|
this.algorithm.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
static async fromSecretStorage(platform: Platform, olm: Olm, secretStorage: SecretStorage, hsApi: HomeServerApi, keyLoader: KeyLoader, storage: Storage, txn: Transaction) {
|
static async fromSecretStorage(platform: Platform, olm: Olm, secretStorage: SecretStorage, hsApi: HomeServerApi, keyLoader: KeyLoader, storage: Storage, txn: Transaction): Promise<KeyBackup | undefined> {
|
||||||
const base64PrivateKey = await secretStorage.readSecret("m.megolm_backup.v1", txn);
|
const base64PrivateKey = await secretStorage.readSecret("m.megolm_backup.v1", txn);
|
||||||
if (base64PrivateKey) {
|
if (base64PrivateKey) {
|
||||||
const privateKey = new Uint8Array(platform.encoding.base64.decode(base64PrivateKey));
|
const privateKey = new Uint8Array(platform.encoding.base64.decode(base64PrivateKey));
|
||||||
const backupInfo = await hsApi.roomKeysVersion().response() as BackupInfo;
|
const backupInfo = await hsApi.roomKeysVersion().response() as BackupInfo;
|
||||||
if (backupInfo.algorithm === Curve25519Algorithm) {
|
if (backupInfo.algorithm === Curve25519Algorithm) {
|
||||||
const algorithm = Curve25519.fromAuthData(backupInfo.auth_data, privateKey, olm);
|
const algorithm = Curve25519.fromAuthData(backupInfo.auth_data, privateKey, olm);
|
||||||
return new SessionBackup(backupInfo, algorithm, hsApi, keyLoader, storage, platform);
|
return new KeyBackup(backupInfo, algorithm, hsApi, keyLoader, storage, platform);
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Unknown backup algorithm: ${backupInfo.algorithm}`);
|
throw new Error(`Unknown backup algorithm: ${backupInfo.algorithm}`);
|
||||||
}
|
}
|
@ -461,11 +461,11 @@ export class BaseRoom extends EventEmitter {
|
|||||||
return observable;
|
return observable;
|
||||||
}
|
}
|
||||||
|
|
||||||
enableSessionBackup(sessionBackup) {
|
enableKeyBackup(keyBackup) {
|
||||||
this._roomEncryption?.enableSessionBackup(sessionBackup);
|
this._roomEncryption?.enableKeyBackup(keyBackup);
|
||||||
// TODO: do we really want to do this every time you open the app?
|
// TODO: do we really want to do this every time you open the app?
|
||||||
if (this._timeline && sessionBackup) {
|
if (this._timeline && keyBackup) {
|
||||||
this._platform.logger.run("enableSessionBackup", log => {
|
this._platform.logger.run("enableKeyBackup", log => {
|
||||||
return this._roomEncryption.restoreMissingSessionsFromBackup(this._timeline.remoteEntries, log);
|
return this._roomEncryption.restoreMissingSessionsFromBackup(this._timeline.remoteEntries, log);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -272,7 +272,7 @@ async function clearAllStores(db: IDBDatabase, txn: IDBTransaction) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// v15 adds the sessionsNeedingBackup store, for session backup
|
// v15 adds the sessionsNeedingBackup store, for key backup
|
||||||
function createSessionsNeedingBackup(db: IDBDatabase): void {
|
function createSessionsNeedingBackup(db: IDBDatabase): void {
|
||||||
db.createObjectStore("sessionsNeedingBackup", {keyPath: "key"});
|
db.createObjectStore("sessionsNeedingBackup", {keyPath: "key"});
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,13 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {TemplateView} from "../general/TemplateView";
|
import {TemplateView} from "../general/TemplateView";
|
||||||
import {SessionBackupSettingsView} from "../session/settings/SessionBackupSettingsView.js";
|
import {KeyBackupSettingsView} from "../session/settings/KeyBackupSettingsView.js";
|
||||||
|
|
||||||
export class AccountSetupView extends TemplateView {
|
export class AccountSetupView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
return t.div({className: "Settings" /* hack for now to get the layout right*/}, [
|
return t.div({className: "Settings" /* hack for now to get the layout right*/}, [
|
||||||
t.h3(vm.i18n`Restore your encrypted history?`),
|
t.h3(vm.i18n`Restore your encrypted history?`),
|
||||||
t.ifView(vm => vm.decryptDehydratedDeviceViewModel, vm => new SessionBackupSettingsView(vm.decryptDehydratedDeviceViewModel)),
|
t.ifView(vm => vm.decryptDehydratedDeviceViewModel, vm => new KeyBackupSettingsView(vm.decryptDehydratedDeviceViewModel)),
|
||||||
t.map(vm => vm.deviceDecrypted, (decrypted, t) => {
|
t.map(vm => vm.deviceDecrypted, (decrypted, t) => {
|
||||||
if (decrypted) {
|
if (decrypted) {
|
||||||
return t.p(vm.i18n`That worked out, you're good to go!`);
|
return t.p(vm.i18n`That worked out, you're good to go!`);
|
||||||
|
@ -26,7 +26,7 @@ export class SessionStatusView extends TemplateView {
|
|||||||
spinner(t, {hidden: vm => !vm.isWaiting}),
|
spinner(t, {hidden: vm => !vm.isWaiting}),
|
||||||
t.p(vm => vm.statusLabel),
|
t.p(vm => vm.statusLabel),
|
||||||
t.if(vm => vm.isConnectNowShown, t => t.button({className: "link", onClick: () => vm.connectNow()}, "Retry now")),
|
t.if(vm => vm.isConnectNowShown, t => t.button({className: "link", onClick: () => vm.connectNow()}, "Retry now")),
|
||||||
t.if(vm => vm.isSecretStorageShown, t => t.a({href: vm.setupSessionBackupUrl}, "Go to settings")),
|
t.if(vm => vm.isSecretStorageShown, t => t.a({href: vm.setupKeyBackupUrl}, "Go to settings")),
|
||||||
t.if(vm => vm.canDismiss, t => t.div({className: "end"}, t.button({className: "dismiss", onClick: () => vm.dismiss()}))),
|
t.if(vm => vm.canDismiss, t => t.div({className: "end"}, t.button({className: "dismiss", onClick: () => vm.dismiss()}))),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||||||
import {TemplateView, InlineTemplateView} from "../../general/TemplateView";
|
import {TemplateView, InlineTemplateView} from "../../general/TemplateView";
|
||||||
import {StaticView} from "../../general/StaticView.js";
|
import {StaticView} from "../../general/StaticView.js";
|
||||||
|
|
||||||
export class SessionBackupSettingsView extends TemplateView {
|
export class KeyBackupSettingsView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
return t.mapView(vm => vm.status, status => {
|
return t.mapView(vm => vm.status, status => {
|
||||||
switch (status) {
|
switch (status) {
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {TemplateView} from "../../general/TemplateView";
|
import {TemplateView} from "../../general/TemplateView";
|
||||||
import {SessionBackupSettingsView} from "./SessionBackupSettingsView.js"
|
import {KeyBackupSettingsView} from "./KeyBackupSettingsView.js"
|
||||||
|
|
||||||
export class SettingsView extends TemplateView {
|
export class SettingsView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
@ -47,8 +47,8 @@ export class SettingsView extends TemplateView {
|
|||||||
}, vm.i18n`Log out`)),
|
}, vm.i18n`Log out`)),
|
||||||
);
|
);
|
||||||
settingNodes.push(
|
settingNodes.push(
|
||||||
t.h3("Session Backup"),
|
t.h3("Key backup"),
|
||||||
t.view(new SessionBackupSettingsView(vm.sessionBackupViewModel))
|
t.view(new KeyBackupSettingsView(vm.keyBackupViewModel))
|
||||||
);
|
);
|
||||||
|
|
||||||
settingNodes.push(
|
settingNodes.push(
|
||||||
|
Loading…
Reference in New Issue
Block a user