diff --git a/src/matrix/Session.js b/src/matrix/Session.js index 874bfecd..17c0cf94 100644 --- a/src/matrix/Session.js +++ b/src/matrix/Session.js @@ -19,7 +19,7 @@ import {Room} from "./room/Room.js"; import {ArchivedRoom} from "./room/ArchivedRoom.js"; import {RoomStatus} from "./room/RoomStatus.js"; import {Invite} from "./room/Invite.js"; -import {Pusher} from "./push/Pusher.js"; +import {Pusher} from "./push/Pusher"; import { ObservableMap } from "../observable/index.js"; import {User} from "./User.js"; import {DeviceMessageHandler} from "./DeviceMessageHandler.js"; diff --git a/src/matrix/SessionContainer.js b/src/matrix/SessionContainer.js index 6e9d190c..44d7b3e4 100644 --- a/src/matrix/SessionContainer.js +++ b/src/matrix/SessionContainer.js @@ -26,9 +26,9 @@ import {MediaRepository} from "./net/MediaRepository.js"; import {RequestScheduler} from "./net/RequestScheduler.js"; import {Sync, SyncStatus} from "./Sync.js"; import {Session} from "./Session.js"; -import {PasswordLoginMethod} from "./login/PasswordLoginMethod.js"; -import {TokenLoginMethod} from "./login/TokenLoginMethod.js"; -import {SSOLoginHelper} from "./login/SSOLoginHelper.js"; +import {PasswordLoginMethod} from "./login/PasswordLoginMethod"; +import {TokenLoginMethod} from "./login/TokenLoginMethod"; +import {SSOLoginHelper} from "./login/SSOLoginHelper"; import {getDehydratedDevice} from "./e2ee/Dehydration.js"; export const LoadStatus = createEnum( diff --git a/src/matrix/login/LoginMethod.js b/src/matrix/login/LoginMethod.ts similarity index 61% rename from src/matrix/login/LoginMethod.js rename to src/matrix/login/LoginMethod.ts index ece18871..2b2a8ff3 100644 --- a/src/matrix/login/LoginMethod.js +++ b/src/matrix/login/LoginMethod.ts @@ -14,17 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -export class LoginMethod { - constructor({homeserver}) { - this.homeserver = homeserver; - } +import type {ILogItem} from "../../logging/types"; +import type {HomeServerApi} from "../net/HomeServerApi.js"; - // eslint-disable-next-line no-unused-vars - async login(hsApi, deviceName, log) { - /* - Regardless of the login method, SessionContainer.startWithLogin() - can do SomeLoginMethod.login() - */ - throw("Not Implemented"); - } +export interface ILoginMethod { + homeserver: string; + login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Promise>; } diff --git a/src/matrix/login/PasswordLoginMethod.js b/src/matrix/login/PasswordLoginMethod.js deleted file mode 100644 index 5c90ccf8..00000000 --- a/src/matrix/login/PasswordLoginMethod.js +++ /dev/null @@ -1,29 +0,0 @@ -/* -Copyright 2021 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import {LoginMethod} from "./LoginMethod.js"; - -export class PasswordLoginMethod extends LoginMethod { - constructor(options) { - super(options); - this.username = options.username; - this.password = options.password; - } - - async login(hsApi, deviceName, log) { - return await hsApi.passwordLogin(this.username, this.password, deviceName, {log}).response(); - } -} diff --git a/src/matrix/login/PasswordLoginMethod.ts b/src/matrix/login/PasswordLoginMethod.ts new file mode 100644 index 00000000..65e96ff0 --- /dev/null +++ b/src/matrix/login/PasswordLoginMethod.ts @@ -0,0 +1,35 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import {ILogItem} from "../../logging/types"; +import {ILoginMethod} from "./LoginMethod"; +import {HomeServerApi} from "../net/HomeServerApi.js"; + +export class PasswordLoginMethod implements ILoginMethod { + private readonly _username: string; + private readonly _password: string; + public readonly homeserver: string; + + constructor({username, password, homeserver}: {username: string, password: string, homeserver: string}) { + this._username = username; + this._password = password; + this.homeserver = homeserver; + } + + async login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Promise> { + return await hsApi.passwordLogin(this._username, this._password, deviceName, {log}).response(); + } +} diff --git a/src/matrix/login/SSOLoginHelper.js b/src/matrix/login/SSOLoginHelper.ts similarity index 80% rename from src/matrix/login/SSOLoginHelper.js rename to src/matrix/login/SSOLoginHelper.ts index a15c8ef9..0fe3d6b8 100644 --- a/src/matrix/login/SSOLoginHelper.js +++ b/src/matrix/login/SSOLoginHelper.ts @@ -15,13 +15,15 @@ limitations under the License. */ export class SSOLoginHelper{ - constructor(homeserver) { + private _homeserver: string; + + constructor(homeserver: string) { this._homeserver = homeserver; } - get homeserver() { return this._homeserver; } + get homeserver(): string { return this._homeserver; } - createSSORedirectURL(returnURL) { + createSSORedirectURL(returnURL: string): string { return `${this._homeserver}/_matrix/client/r0/login/sso/redirect?redirectUrl=${returnURL}`; } } diff --git a/src/matrix/login/TokenLoginMethod.js b/src/matrix/login/TokenLoginMethod.ts similarity index 57% rename from src/matrix/login/TokenLoginMethod.js rename to src/matrix/login/TokenLoginMethod.ts index e55cedcf..4f1e3cc7 100644 --- a/src/matrix/login/TokenLoginMethod.js +++ b/src/matrix/login/TokenLoginMethod.ts @@ -14,16 +14,21 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {LoginMethod} from "./LoginMethod.js"; import {makeTxnId} from "../common.js"; +import {ILogItem} from "../../logging/types"; +import {ILoginMethod} from "./LoginMethod"; +import {HomeServerApi} from "../net/HomeServerApi.js"; -export class TokenLoginMethod extends LoginMethod { - constructor(options) { - super(options); - this._loginToken = options.loginToken; +export class TokenLoginMethod implements ILoginMethod { + private readonly _loginToken: string; + public readonly homeserver: string; + + constructor({ homeserver, loginToken }: { homeserver: string, loginToken: string}) { + this.homeserver = homeserver; + this._loginToken = loginToken; } - async login(hsApi, deviceName, log) { + async login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Promise> { return await hsApi.tokenLogin(this._loginToken, makeTxnId(), deviceName, {log}).response(); } } diff --git a/src/matrix/push/Pusher.js b/src/matrix/push/Pusher.js deleted file mode 100644 index 99baeae6..00000000 --- a/src/matrix/push/Pusher.js +++ /dev/null @@ -1,50 +0,0 @@ -export class Pusher { - constructor(description) { - this._description = description; - } - - static httpPusher(host, appId, pushkey, data) { - return new Pusher({ - kind: "http", - append: true, // as pushkeys are shared between multiple users on one origin - data: Object.assign({}, data, {url: host + "/_matrix/push/v1/notify"}), - pushkey, - app_id: appId, - app_display_name: "Hydrogen", - device_display_name: "Hydrogen", - lang: "en" - }); - } - - static createDefaultPayload(sessionId) { - return {session_id: sessionId}; - } - - async enable(hsApi, log) { - try { - log.set("endpoint", new URL(this._description.data.endpoint).host); - } catch { - log.set("endpoint", null); - } - await hsApi.setPusher(this._description, {log}).response(); - } - - async disable(hsApi, log) { - const deleteDescription = Object.assign({}, this._description, {kind: null}); - await hsApi.setPusher(deleteDescription, {log}).response(); - } - - serialize() { - return this._description; - } - - equals(pusher) { - if (this._description.app_id !== pusher._description.app_id) { - return false; - } - if (this._description.pushkey !== pusher._description.pushkey) { - return false; - } - return JSON.stringify(this._description.data) === JSON.stringify(pusher._description.data); - } -} diff --git a/src/matrix/push/Pusher.ts b/src/matrix/push/Pusher.ts new file mode 100644 index 00000000..9f970322 --- /dev/null +++ b/src/matrix/push/Pusher.ts @@ -0,0 +1,90 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import type {HomeServerApi} from "../net/HomeServerApi.js"; +import type {ILogItem} from "../../logging/types"; + +export interface IPusherDescription { + kind: "http" | "email" | "null"; + lang: string; + device_display_name: string; + app_display_name: string; + app_id: string; + pushkey: string; + data: IPusherData; + append?: boolean; + profile_tag?: string; +} + +interface IPusherData { + format?: string; + url?: string; + endpoint?: PushSubscriptionJSON["endpoint"]; + keys?: PushSubscriptionJSON["keys"]; +} + +export class Pusher { + private readonly _description: IPusherDescription; + + constructor(description: IPusherDescription) { + this._description = description; + } + + static httpPusher(host: string, appId: string, pushkey: string, data: IPusherData): Pusher { + return new Pusher({ + kind: "http", + append: true, // as pushkeys are shared between multiple users on one origin + data: Object.assign({}, data, {url: host + "/_matrix/push/v1/notify"}), + pushkey, + app_id: appId, + app_display_name: "Hydrogen", + device_display_name: "Hydrogen", + lang: "en" + }); + } + + static createDefaultPayload(sessionId: string): {session_id: string} { + return {session_id: sessionId}; + } + + async enable(hsApi: HomeServerApi, log: ILogItem): Promise { + try { + log.set("endpoint", new URL(this._description.data.endpoint!).host); + } catch { + log.set("endpoint", null); + } + await hsApi.setPusher(this._description, {log}).response(); + } + + async disable(hsApi: HomeServerApi, log: ILogItem): Promise { + const deleteDescription = Object.assign({}, this._description, {kind: null}); + await hsApi.setPusher(deleteDescription, {log}).response(); + } + + serialize(): IPusherDescription { + return this._description; + } + + equals(pusher): boolean { + if (this._description.app_id !== pusher._description.app_id) { + return false; + } + if (this._description.pushkey !== pusher._description.pushkey) { + return false; + } + return JSON.stringify(this._description.data) === JSON.stringify(pusher._description.data); + } +} diff --git a/src/matrix/sessioninfo/localstorage/SessionInfoStorage.js b/src/matrix/sessioninfo/localstorage/SessionInfoStorage.ts similarity index 64% rename from src/matrix/sessioninfo/localstorage/SessionInfoStorage.js rename to src/matrix/sessioninfo/localstorage/SessionInfoStorage.ts index ce795916..ebe575f6 100644 --- a/src/matrix/sessioninfo/localstorage/SessionInfoStorage.js +++ b/src/matrix/sessioninfo/localstorage/SessionInfoStorage.ts @@ -14,12 +14,33 @@ See the License for the specific language governing permissions and limitations under the License. */ -export class SessionInfoStorage { - constructor(name) { +interface ISessionInfo { + id: string; + deviceId: string; + userId: string; + homeserver: string; + homeServer: string; // deprecate this over time + accessToken: string; + lastUsed: number; +} + +// todo: this should probably be in platform/types? +interface ISessionInfoStorage { + getAll(): Promise; + updateLastUsed(id: string, timestamp: number): Promise; + get(id: string): Promise; + add(sessionInfo: ISessionInfo): Promise; + delete(sessionId: string): Promise; +} + +export class SessionInfoStorage implements ISessionInfoStorage { + private readonly _name: string; + + constructor(name: string) { this._name = name; } - getAll() { + getAll(): Promise { const sessionsJson = localStorage.getItem(this._name); if (sessionsJson) { const sessions = JSON.parse(sessionsJson); @@ -30,7 +51,7 @@ export class SessionInfoStorage { return Promise.resolve([]); } - async updateLastUsed(id, timestamp) { + async updateLastUsed(id: string, timestamp: number): Promise { const sessions = await this.getAll(); if (sessions) { const session = sessions.find(session => session.id === id); @@ -41,20 +62,20 @@ export class SessionInfoStorage { } } - async get(id) { + async get(id: string): Promise { const sessions = await this.getAll(); if (sessions) { return sessions.find(session => session.id === id); } } - async add(sessionInfo) { + async add(sessionInfo: ISessionInfo): Promise { const sessions = await this.getAll(); sessions.push(sessionInfo); localStorage.setItem(this._name, JSON.stringify(sessions)); } - async delete(sessionId) { + async delete(sessionId: string): Promise { let sessions = await this.getAll(); sessions = sessions.filter(s => s.id !== sessionId); localStorage.setItem(this._name, JSON.stringify(sessions)); diff --git a/src/platform/web/Platform.js b/src/platform/web/Platform.js index 569daeb4..4f0446ce 100644 --- a/src/platform/web/Platform.js +++ b/src/platform/web/Platform.js @@ -17,7 +17,7 @@ limitations under the License. import {createFetchRequest} from "./dom/request/fetch.js"; import {xhrRequest} from "./dom/request/xhr.js"; import {StorageFactory} from "../../matrix/storage/idb/StorageFactory"; -import {SessionInfoStorage} from "../../matrix/sessioninfo/localstorage/SessionInfoStorage.js"; +import {SessionInfoStorage} from "../../matrix/sessioninfo/localstorage/SessionInfoStorage"; import {SettingsStorage} from "./dom/SettingsStorage.js"; import {Encoding} from "./utils/Encoding.js"; import {OlmWorker} from "../../matrix/e2ee/OlmWorker.js";