From 85a9a019c8d164ca9a2fe2eb237699bac4366a4e Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 11 Oct 2022 17:58:07 +0530 Subject: [PATCH 1/6] Don't inhibit login --- src/matrix/net/HomeServerApi.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/net/HomeServerApi.ts b/src/matrix/net/HomeServerApi.ts index e9902ef8..bb791577 100644 --- a/src/matrix/net/HomeServerApi.ts +++ b/src/matrix/net/HomeServerApi.ts @@ -164,7 +164,7 @@ export class HomeServerApi { return this._unauthedRequest("GET", this._url("/login")); } - register(username: string | null, password: string, initialDeviceDisplayName: string, auth?: Record, inhibitLogin: boolean = true , options: BaseRequestOptions = {}): IHomeServerRequest { + register(username: string | null, password: string, initialDeviceDisplayName: string, auth?: Record, inhibitLogin: boolean = false , options: BaseRequestOptions = {}): IHomeServerRequest { options.allowedStatusCodes = [401]; const body: any = { auth, From 1f764664c9c08bc42da36a9168f0e84bf707f744 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 11 Oct 2022 17:58:33 +0530 Subject: [PATCH 2/6] Expose homeserver from Registration object --- src/matrix/registration/Registration.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/matrix/registration/Registration.ts b/src/matrix/registration/Registration.ts index ded66719..e47bc2db 100644 --- a/src/matrix/registration/Registration.ts +++ b/src/matrix/registration/Registration.ts @@ -35,8 +35,10 @@ export class Registration { private readonly _accountDetails: AccountDetails; private readonly _flowSelector: FlowSelector; private _sessionInfo?: RegistrationResponseSuccess + public readonly homeserver: string; - constructor(hsApi: HomeServerApi, accountDetails: AccountDetails, flowSelector?: FlowSelector) { + constructor(homeserver: string, hsApi: HomeServerApi, accountDetails: AccountDetails, flowSelector?: FlowSelector) { + this.homeserver = homeserver; this._hsApi = hsApi; this._accountDetails = accountDetails; this._flowSelector = flowSelector ?? (flows => flows[0]); From a448c0218defbc104e2116d7f76d92c194e2826a Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 11 Oct 2022 18:01:54 +0530 Subject: [PATCH 3/6] Fix missing semicolon --- src/matrix/registration/Registration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/registration/Registration.ts b/src/matrix/registration/Registration.ts index e47bc2db..82e3ade5 100644 --- a/src/matrix/registration/Registration.ts +++ b/src/matrix/registration/Registration.ts @@ -34,7 +34,7 @@ export class Registration { private readonly _hsApi: HomeServerApi; private readonly _accountDetails: AccountDetails; private readonly _flowSelector: FlowSelector; - private _sessionInfo?: RegistrationResponseSuccess + private _sessionInfo?: RegistrationResponseSuccess; public readonly homeserver: string; constructor(homeserver: string, hsApi: HomeServerApi, accountDetails: AccountDetails, flowSelector?: FlowSelector) { From dcba6d1500e13492240c90d35eada669210544d4 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 11 Oct 2022 18:05:54 +0530 Subject: [PATCH 4/6] Split method --- src/matrix/Client.js | 48 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/src/matrix/Client.js b/src/matrix/Client.js index f81b9085..2670ce07 100644 --- a/src/matrix/Client.js +++ b/src/matrix/Client.js @@ -137,7 +137,7 @@ export class Client { async startRegistration(homeserver, username, password, initialDeviceDisplayName, flowSelector) { const request = this._platform.request; const hsApi = new HomeServerApi({homeserver, request}); - const registration = new Registration(hsApi, { + const registration = new Registration(homeserver, hsApi, { username, password, initialDeviceDisplayName, @@ -146,6 +146,21 @@ export class Client { return registration; } + async startWithFinishedRegistration(registration) { + this._platform.logger.run("startWithFinishedRegistration", async (log) => { + const sessionInfo = registration.sessionInfo; + if (!sessionInfo) { + throw new Error("Registration.sessionInfo is not available; are you sure that registration is finished?"); + } + await this.startWithSessionInfo({ + accessToken: sessionInfo.access_token, + deviceId: sessionInfo.device_id, + userId: sessionInfo.user_id, + homeserver: registration.homeserver, + }, true, log); + }); + } + async startWithLogin(loginMethod, {inspectAccountSetup} = {}) { const currentStatus = this._status.get(); if (currentStatus !== LoadStatus.LoginFailed && @@ -156,23 +171,17 @@ export class Client { this._resetStatus(); await this._platform.logger.run("login", async log => { this._status.set(LoadStatus.Login); - const clock = this._platform.clock; let sessionInfo; try { const request = this._platform.request; const hsApi = new HomeServerApi({homeserver: loginMethod.homeserver, request}); const loginData = await loginMethod.login(hsApi, "Hydrogen", log); - const sessionId = this.createNewSessionId(); sessionInfo = { - id: sessionId, deviceId: loginData.device_id, userId: loginData.user_id, - homeServer: loginMethod.homeserver, // deprecate this over time homeserver: loginMethod.homeserver, accessToken: loginData.access_token, - lastUsed: clock.now() }; - log.set("id", sessionId); } catch (err) { this._error = err; if (err.name === "HomeServerError") { @@ -191,9 +200,26 @@ export class Client { } return; } + await this.startWithSessionInfo(sessionInfo, inspectAccountSetup, log); + }); + } + + async startWithSessionInfo({deviceId, userId, accessToken, homeserver}, inspectAccountSetup, log) { + await log.wrap("startWithSessionInfo", async (l) => { + const id = this.createNewSessionId(); + const lastUsed = this._platform.clock.now(); + const sessionInfo = { + id, + deviceId, + userId, + homeServer: homeserver, // deprecate this over time + homeserver, + accessToken, + lastUsed, + }; let dehydratedDevice; if (inspectAccountSetup) { - dehydratedDevice = await this._inspectAccountAfterLogin(sessionInfo, log); + dehydratedDevice = await this._inspectAccountAfterLogin(sessionInfo, l); if (dehydratedDevice) { sessionInfo.deviceId = dehydratedDevice.deviceId; } @@ -203,10 +229,10 @@ export class Client { // LoadStatus.Error in case of an error, // so separate try/catch try { - await this._loadSessionInfo(sessionInfo, dehydratedDevice, log); - log.set("status", this._status.get()); + await this._loadSessionInfo(sessionInfo, dehydratedDevice, l); + l.set("status", this._status.get()); } catch (err) { - log.catch(err); + l.catch(err); // free olm Account that might be contained dehydratedDevice?.dispose(); this._error = err; From f46d2c1bf5ee01432bc2ef09296d72c194534ecf Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Fri, 14 Oct 2022 10:17:32 +0200 Subject: [PATCH 5/6] make startWithFinishedRegistration more broadly useful --- src/matrix/Client.js | 25 ++++++++++--------------- src/matrix/registration/Registration.ts | 16 ++++++++++++---- src/matrix/registration/types.ts | 7 +++++++ 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/matrix/Client.js b/src/matrix/Client.js index 2670ce07..4d6f7bb5 100644 --- a/src/matrix/Client.js +++ b/src/matrix/Client.js @@ -146,18 +146,13 @@ export class Client { return registration; } - async startWithFinishedRegistration(registration) { - this._platform.logger.run("startWithFinishedRegistration", async (log) => { - const sessionInfo = registration.sessionInfo; - if (!sessionInfo) { - throw new Error("Registration.sessionInfo is not available; are you sure that registration is finished?"); - } - await this.startWithSessionInfo({ - accessToken: sessionInfo.access_token, - deviceId: sessionInfo.device_id, - userId: sessionInfo.user_id, - homeserver: registration.homeserver, - }, true, log); + /** 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}) { + this._platform.logger.run("startWithAuthData", async (log) => { + await this._createSessionAfterAuth({accessToken, deviceId, userId, homeserver}, true, log); }); } @@ -200,12 +195,12 @@ export class Client { } return; } - await this.startWithSessionInfo(sessionInfo, inspectAccountSetup, log); + await this._createSessionAfterAuth(sessionInfo, inspectAccountSetup, log); }); } - async startWithSessionInfo({deviceId, userId, accessToken, homeserver}, inspectAccountSetup, log) { - await log.wrap("startWithSessionInfo", async (l) => { + async _createSessionAfterAuth({deviceId, userId, accessToken, homeserver}, inspectAccountSetup, log) { + await log.wrap("_createSessionAfterAuth", async (l) => { const id = this.createNewSessionId(); const lastUsed = this._platform.clock.now(); const sessionInfo = { diff --git a/src/matrix/registration/Registration.ts b/src/matrix/registration/Registration.ts index 82e3ade5..5440d66d 100644 --- a/src/matrix/registration/Registration.ts +++ b/src/matrix/registration/Registration.ts @@ -25,6 +25,7 @@ import type { RegistrationResponseMoreDataNeeded, RegistrationResponse, RegistrationResponseSuccess, + AuthData, RegistrationParams, } from "./types"; @@ -34,7 +35,7 @@ export class Registration { private readonly _hsApi: HomeServerApi; private readonly _accountDetails: AccountDetails; private readonly _flowSelector: FlowSelector; - private _sessionInfo?: RegistrationResponseSuccess; + private _registerResponse?: RegistrationResponseSuccess; public readonly homeserver: string; constructor(homeserver: string, hsApi: HomeServerApi, accountDetails: AccountDetails, flowSelector?: FlowSelector) { @@ -93,7 +94,7 @@ export class Registration { private async parseRegistrationResponse(response: RegistrationResponse, currentStage: BaseRegistrationStage) { switch (response.status) { case 200: - this._sessionInfo = response; + this._registerResponse = response; return undefined; case 401: if (response.completed?.includes(currentStage.type)) { @@ -119,7 +120,14 @@ export class Registration { } } - get sessionInfo(): RegistrationResponseSuccess | undefined { - return this._sessionInfo; + get authData(): AuthData | undefined { + if (this._registerResponse) { + return { + accessToken: this._registerResponse.access_token, + homeserver: this.homeserver, + userId: this._registerResponse.user_id, + deviceId: this._registerResponse.device_id, + }; + } } } diff --git a/src/matrix/registration/types.ts b/src/matrix/registration/types.ts index f1ddbe98..7e0d01ff 100644 --- a/src/matrix/registration/types.ts +++ b/src/matrix/registration/types.ts @@ -38,6 +38,13 @@ export type RegistrationResponseSuccess = { status: 200; } +export type AuthData = { + userId: string; + deviceId: string; + homeserver: string; + accessToken?: string; +} + export type RegistrationFlow = { stages: string[]; } From 1f8a591cf64d9793f45295d52d8717b52ce9c327 Mon Sep 17 00:00:00 2001 From: Bruno Windels <274386+bwindels@users.noreply.github.com> Date: Fri, 14 Oct 2022 10:28:42 +0200 Subject: [PATCH 6/6] dont need extra log depth --- src/matrix/Client.js | 64 +++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/src/matrix/Client.js b/src/matrix/Client.js index 4d6f7bb5..68eeed27 100644 --- a/src/matrix/Client.js +++ b/src/matrix/Client.js @@ -200,40 +200,38 @@ export class Client { } async _createSessionAfterAuth({deviceId, userId, accessToken, homeserver}, inspectAccountSetup, log) { - await log.wrap("_createSessionAfterAuth", async (l) => { - const id = this.createNewSessionId(); - const lastUsed = this._platform.clock.now(); - const sessionInfo = { - id, - deviceId, - userId, - homeServer: homeserver, // deprecate this over time - homeserver, - accessToken, - lastUsed, - }; - let dehydratedDevice; - if (inspectAccountSetup) { - dehydratedDevice = await this._inspectAccountAfterLogin(sessionInfo, l); - if (dehydratedDevice) { - sessionInfo.deviceId = dehydratedDevice.deviceId; - } + const id = this.createNewSessionId(); + const lastUsed = this._platform.clock.now(); + const sessionInfo = { + id, + deviceId, + userId, + homeServer: homeserver, // deprecate this over time + homeserver, + accessToken, + lastUsed, + }; + let dehydratedDevice; + if (inspectAccountSetup) { + dehydratedDevice = await this._inspectAccountAfterLogin(sessionInfo, log); + if (dehydratedDevice) { + sessionInfo.deviceId = dehydratedDevice.deviceId; } - await this._platform.sessionInfoStorage.add(sessionInfo); - // loading the session can only lead to - // LoadStatus.Error in case of an error, - // so separate try/catch - try { - await this._loadSessionInfo(sessionInfo, dehydratedDevice, l); - l.set("status", this._status.get()); - } catch (err) { - l.catch(err); - // free olm Account that might be contained - dehydratedDevice?.dispose(); - this._error = err; - this._status.set(LoadStatus.Error); - } - }); + } + await this._platform.sessionInfoStorage.add(sessionInfo); + // loading the session can only lead to + // LoadStatus.Error in case of an error, + // so separate try/catch + try { + await this._loadSessionInfo(sessionInfo, dehydratedDevice, log); + log.set("status", this._status.get()); + } catch (err) { + log.catch(err); + // free olm Account that might be contained + dehydratedDevice?.dispose(); + this._error = err; + this._status.set(LoadStatus.Error); + } } async _loadSessionInfo(sessionInfo, dehydratedDevice, log) {