forked from mystiq/hydrogen-web
WIP2
This commit is contained in:
parent
faf4ea6434
commit
718b410253
5 changed files with 51 additions and 42 deletions
|
@ -24,6 +24,7 @@ import { ObservableMap } from "../observable/index.js";
|
|||
import {User} from "./User.js";
|
||||
import {DeviceMessageHandler} from "./DeviceMessageHandler.js";
|
||||
import {Account as E2EEAccount} from "./e2ee/Account.js";
|
||||
import {uploadAccountAsDehydratedDevice} from "./e2ee/Dehydration.js";
|
||||
import {Decryption as OlmDecryption} from "./e2ee/olm/Decryption.js";
|
||||
import {Encryption as OlmEncryption} from "./e2ee/olm/Encryption.js";
|
||||
import {Decryption as MegOlmDecryption} from "./e2ee/megolm/Decryption";
|
||||
|
@ -284,8 +285,8 @@ export class Session {
|
|||
pickleKey: PICKLE_KEY,
|
||||
userId: this._sessionInfo.userId,
|
||||
olmWorker: this._olmWorker,
|
||||
deviceId,
|
||||
storage,
|
||||
deviceId: this.deviceId,
|
||||
storage: this._storage,
|
||||
});
|
||||
log.set("keys", this._e2eeAccount.identityKeys);
|
||||
this._setupEncryption();
|
||||
|
|
|
@ -29,6 +29,7 @@ import {Session} from "./Session.js";
|
|||
import {PasswordLoginMethod} from "./login/PasswordLoginMethod.js";
|
||||
import {TokenLoginMethod} from "./login/TokenLoginMethod.js";
|
||||
import {SSOLoginHelper} from "./login/SSOLoginHelper.js";
|
||||
import {getDehydratedDevice} from "./e2ee/Dehydration.js";
|
||||
|
||||
export const LoadStatus = createEnum(
|
||||
"NotLoading",
|
||||
|
@ -38,7 +39,7 @@ export const LoadStatus = createEnum(
|
|||
"SetupAccount", // asked to restore from dehydrated device if present, call sc.accountSetup.finish() to progress to the next stage
|
||||
"Loading",
|
||||
"SessionSetup", // upload e2ee keys, ...
|
||||
"Migrating", //not used atm, but would fit here
|
||||
"Migrating", // not used atm, but would fit here
|
||||
"FirstSync",
|
||||
"Error",
|
||||
"Ready",
|
||||
|
@ -174,7 +175,7 @@ export class SessionContainer {
|
|||
}
|
||||
return;
|
||||
}
|
||||
const dehydratedDevice = await this._inspectAccountAfterLogin(sessionInfo);
|
||||
const dehydratedDevice = await this._inspectAccountAfterLogin(sessionInfo, log);
|
||||
if (dehydratedDevice) {
|
||||
sessionInfo.deviceId = dehydratedDevice.deviceId;
|
||||
}
|
||||
|
@ -240,7 +241,7 @@ export class SessionContainer {
|
|||
});
|
||||
await this._session.load(log);
|
||||
if (dehydratedDevice) {
|
||||
await log.wrap("dehydrateIdentity", log => await this._session.dehydrateIdentity(dehydratedDevice, log));
|
||||
await log.wrap("dehydrateIdentity", log => this._session.dehydrateIdentity(dehydratedDevice, log));
|
||||
} else if (!this._session.hasIdentity) {
|
||||
this._status.set(LoadStatus.SessionSetup);
|
||||
await log.wrap("createIdentity", log => this._session.createIdentity(log));
|
||||
|
@ -308,25 +309,27 @@ export class SessionContainer {
|
|||
}
|
||||
}
|
||||
|
||||
async _inspectAccountAfterLogin(sessionInfo) {
|
||||
this._status.set(LoadStatus.QueryAccount);
|
||||
const hsApi = new HomeServerApi({
|
||||
homeserver: sessionInfo.homeServer,
|
||||
accessToken: sessionInfo.accessToken,
|
||||
request: this._platform.request,
|
||||
_inspectAccountAfterLogin(sessionInfo, log) {
|
||||
return log.wrap("inspectAccount", async log => {
|
||||
this._status.set(LoadStatus.QueryAccount);
|
||||
const hsApi = new HomeServerApi({
|
||||
homeserver: sessionInfo.homeServer,
|
||||
accessToken: sessionInfo.accessToken,
|
||||
request: this._platform.request,
|
||||
});
|
||||
const olm = await this._olmPromise;
|
||||
const encryptedDehydratedDevice = await getDehydratedDevice(hsApi, olm, log);
|
||||
if (encryptedDehydratedDevice) {
|
||||
let resolveStageFinish;
|
||||
const promiseStageFinish = new Promise(r => resolveStageFinish = r);
|
||||
this._accountSetup = new AccountSetup(encryptedDehydratedDevice, resolveStageFinish);
|
||||
this._status.set(LoadStatus.SetupAccount);
|
||||
await promiseStageFinish;
|
||||
const dehydratedDevice = this._accountSetup?._dehydratedDevice;
|
||||
this._accountSetup = null;
|
||||
return dehydratedDevice;
|
||||
}
|
||||
});
|
||||
const olm = await this._olmPromise;
|
||||
const encryptedDehydratedDevice = await getDehydratedDevice(hsApi, olm);
|
||||
if (encryptedDehydratedDevice) {
|
||||
let resolveStageFinish;
|
||||
const promiseStageFinish = new Promise(r => resolveStageFinish = r);
|
||||
this._accountSetup = new AccountSetup(encryptedDehydratedDevice, resolveStageFinish);
|
||||
this._status.set(LoadStatus.SetupAccount);
|
||||
await promiseStageFinish;
|
||||
const dehydratedDevice = this._accountSetup?._dehydratedDevice;
|
||||
this._accountSetup = null;
|
||||
return dehydratedDevice;
|
||||
}
|
||||
}
|
||||
|
||||
get accountSetup() {
|
||||
|
|
|
@ -52,14 +52,14 @@ export class Account {
|
|||
deviceId, areDeviceKeysUploaded, serverOTKCount, olm, olmWorker});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static async adoptDehydratedDevice({olm, dehydratedDevice, pickleKey, hsApi, userId, olmWorker, storage}) {
|
||||
const account = dehydratedDevice.adoptUnpickledOlmAccount();
|
||||
const areDeviceKeysUploaded = true;
|
||||
const oneTimeKeys = JSON.parse(this._account.one_time_keys());
|
||||
const oneTimeKeys = JSON.parse(account.one_time_keys());
|
||||
// only one algorithm supported by olm atm, so hardcode its name
|
||||
const oneTimeKeysEntries = Object.entries(oneTimeKeys.curve25519);
|
||||
const serverOTKCount = oneTimeKeysEntries.length;
|
||||
const areDeviceKeysUploaded = true;
|
||||
await initiallyStoreAccount(account, pickleKey, areDeviceKeysUploaded, serverOTKCount, storage);
|
||||
return new Account({
|
||||
pickleKey, hsApi, account, userId,
|
||||
|
@ -76,11 +76,13 @@ export class Account {
|
|||
account.create();
|
||||
account.generate_one_time_keys(account.max_number_of_one_time_keys());
|
||||
}
|
||||
const areDeviceKeysUploaded = false;
|
||||
const serverOTKCount = 0;
|
||||
if (storage) {
|
||||
await initiallyStoreAccount(account, pickleKey, false, 0, storage);
|
||||
await initiallyStoreAccount(account, pickleKey, areDeviceKeysUploaded, serverOTKCount, storage);
|
||||
}
|
||||
return new Account({pickleKey, hsApi, account, userId,
|
||||
deviceId, areDeviceKeysUploaded, serverOTKCount: 0, olm, olmWorker});
|
||||
deviceId, areDeviceKeysUploaded, serverOTKCount, olm, olmWorker});
|
||||
}
|
||||
|
||||
constructor({pickleKey, hsApi, account, userId, deviceId, areDeviceKeysUploaded, serverOTKCount, olm, olmWorker}) {
|
||||
|
|
|
@ -14,20 +14,23 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
export const DEHYDRATION_LIBOLM_PICKLE_ALGORITHM = "org.matrix.msc2697.v1.olm.libolm_pickle";
|
||||
const DEHYDRATION_LIBOLM_PICKLE_ALGORITHM = "org.matrix.msc2697.v1.olm.libolm_pickle";
|
||||
|
||||
async function getDehydratedDevice(hsApi, olm) {
|
||||
const response = await hsApi.getDehydratedDevice().response();
|
||||
if (response.device_data.algorithm === DEHYDRATION_LIBOLM_PICKLE_ALGORITHM) {
|
||||
return new DehydratedDevice(response, olm);
|
||||
export async function getDehydratedDevice(hsApi, olm, log) {
|
||||
try {
|
||||
const response = await hsApi.getDehydratedDevice({log}).response();
|
||||
if (response.device_data.algorithm === DEHYDRATION_LIBOLM_PICKLE_ALGORITHM) {
|
||||
return new EncryptedDehydratedDevice(response, olm);
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.name !== "HomeServerError") {
|
||||
log.error = err;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
async function hasRemainingDevice(ownUserId, ownDeviceId, storage) {
|
||||
|
||||
}
|
||||
|
||||
async function uploadAccountAsDehydratedDevice(account, hsApi, key, deviceDisplayName, log) {
|
||||
export async function uploadAccountAsDehydratedDevice(account, hsApi, key, deviceDisplayName, log) {
|
||||
const response = await hsApi.createDehydratedDevice({
|
||||
device_data: {
|
||||
algorithm: DEHYDRATION_LIBOLM_PICKLE_ALGORITHM,
|
||||
|
@ -66,7 +69,7 @@ class DehydratedDevice {
|
|||
this._account = account;
|
||||
}
|
||||
|
||||
claim(hsApi, log) {
|
||||
async claim(hsApi, log) {
|
||||
try {
|
||||
const response = await hsApi.claimDehydratedDevice(this.deviceId, {log}).response();
|
||||
return response.success;
|
||||
|
@ -83,6 +86,6 @@ class DehydratedDevice {
|
|||
}
|
||||
|
||||
get deviceId() {
|
||||
this._dehydratedDevice.device_id;
|
||||
return this._dehydratedDevice.device_id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,12 +242,12 @@ export class HomeServerApi {
|
|||
return this._get(`/dehydrated_device`, null, null, options);
|
||||
}
|
||||
|
||||
createDehydratedDevice(payload, options = null) {
|
||||
createDehydratedDevice(payload, options = {}) {
|
||||
options.prefix = DEHYDRATION_PREFIX;
|
||||
return this._put(`/dehydrated_device`, null, payload, options);
|
||||
}
|
||||
|
||||
claimDehydratedDevice(deviceId) {
|
||||
claimDehydratedDevice(deviceId, options = {}) {
|
||||
options.prefix = DEHYDRATION_PREFIX;
|
||||
return this._post(`/dehydrated_device/claim`, null, {device_id: deviceId}, options);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue