forked from mystiq/hydrogen-web
Merge branch 'master' into bwindels/vite-mvp
This commit is contained in:
commit
0ec86b6dc1
11 changed files with 179 additions and 112 deletions
|
@ -19,7 +19,7 @@ import {Room} from "./room/Room.js";
|
||||||
import {ArchivedRoom} from "./room/ArchivedRoom.js";
|
import {ArchivedRoom} from "./room/ArchivedRoom.js";
|
||||||
import {RoomStatus} from "./room/RoomStatus.js";
|
import {RoomStatus} from "./room/RoomStatus.js";
|
||||||
import {Invite} from "./room/Invite.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 { ObservableMap } from "../observable/index.js";
|
||||||
import {User} from "./User.js";
|
import {User} from "./User.js";
|
||||||
import {DeviceMessageHandler} from "./DeviceMessageHandler.js";
|
import {DeviceMessageHandler} from "./DeviceMessageHandler.js";
|
||||||
|
|
|
@ -26,9 +26,9 @@ import {MediaRepository} from "./net/MediaRepository.js";
|
||||||
import {RequestScheduler} from "./net/RequestScheduler.js";
|
import {RequestScheduler} from "./net/RequestScheduler.js";
|
||||||
import {Sync, SyncStatus} from "./Sync.js";
|
import {Sync, SyncStatus} from "./Sync.js";
|
||||||
import {Session} from "./Session.js";
|
import {Session} from "./Session.js";
|
||||||
import {PasswordLoginMethod} from "./login/PasswordLoginMethod.js";
|
import {PasswordLoginMethod} from "./login/PasswordLoginMethod";
|
||||||
import {TokenLoginMethod} from "./login/TokenLoginMethod.js";
|
import {TokenLoginMethod} from "./login/TokenLoginMethod";
|
||||||
import {SSOLoginHelper} from "./login/SSOLoginHelper.js";
|
import {SSOLoginHelper} from "./login/SSOLoginHelper";
|
||||||
import {getDehydratedDevice} from "./e2ee/Dehydration.js";
|
import {getDehydratedDevice} from "./e2ee/Dehydration.js";
|
||||||
|
|
||||||
export const LoadStatus = createEnum(
|
export const LoadStatus = createEnum(
|
||||||
|
|
|
@ -14,17 +14,10 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export class LoginMethod {
|
import type {ILogItem} from "../../logging/types";
|
||||||
constructor({homeserver}) {
|
import type {HomeServerApi} from "../net/HomeServerApi.js";
|
||||||
this.homeserver = homeserver;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
export interface ILoginMethod {
|
||||||
async login(hsApi, deviceName, log) {
|
homeserver: string;
|
||||||
/*
|
login(hsApi: HomeServerApi, deviceName: string, log: ILogItem): Promise<Record<string, any>>;
|
||||||
Regardless of the login method, SessionContainer.startWithLogin()
|
|
||||||
can do SomeLoginMethod.login()
|
|
||||||
*/
|
|
||||||
throw("Not Implemented");
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
35
src/matrix/login/PasswordLoginMethod.ts
Normal file
35
src/matrix/login/PasswordLoginMethod.ts
Normal file
|
@ -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<Record<string, any>> {
|
||||||
|
return await hsApi.passwordLogin(this._username, this._password, deviceName, {log}).response();
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,13 +15,15 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export class SSOLoginHelper{
|
export class SSOLoginHelper{
|
||||||
constructor(homeserver) {
|
private _homeserver: string;
|
||||||
|
|
||||||
|
constructor(homeserver: string) {
|
||||||
this._homeserver = homeserver;
|
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}`;
|
return `${this._homeserver}/_matrix/client/r0/login/sso/redirect?redirectUrl=${returnURL}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,16 +14,21 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {LoginMethod} from "./LoginMethod.js";
|
|
||||||
import {makeTxnId} from "../common.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 {
|
export class TokenLoginMethod implements ILoginMethod {
|
||||||
constructor(options) {
|
private readonly _loginToken: string;
|
||||||
super(options);
|
public readonly homeserver: string;
|
||||||
this._loginToken = options.loginToken;
|
|
||||||
|
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<Record<string, any>> {
|
||||||
return await hsApi.tokenLogin(this._loginToken, makeTxnId(), deviceName, {log}).response();
|
return await hsApi.tokenLogin(this._loginToken, makeTxnId(), deviceName, {log}).response();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
90
src/matrix/push/Pusher.ts
Normal file
90
src/matrix/push/Pusher.ts
Normal file
|
@ -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<void> {
|
||||||
|
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<void> {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,12 +14,33 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export class SessionInfoStorage {
|
interface ISessionInfo {
|
||||||
constructor(name) {
|
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<ISessionInfo[]>;
|
||||||
|
updateLastUsed(id: string, timestamp: number): Promise<void>;
|
||||||
|
get(id: string): Promise<ISessionInfo | undefined>;
|
||||||
|
add(sessionInfo: ISessionInfo): Promise<void>;
|
||||||
|
delete(sessionId: string): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SessionInfoStorage implements ISessionInfoStorage {
|
||||||
|
private readonly _name: string;
|
||||||
|
|
||||||
|
constructor(name: string) {
|
||||||
this._name = name;
|
this._name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
getAll() {
|
getAll(): Promise<ISessionInfo[]> {
|
||||||
const sessionsJson = localStorage.getItem(this._name);
|
const sessionsJson = localStorage.getItem(this._name);
|
||||||
if (sessionsJson) {
|
if (sessionsJson) {
|
||||||
const sessions = JSON.parse(sessionsJson);
|
const sessions = JSON.parse(sessionsJson);
|
||||||
|
@ -30,7 +51,7 @@ export class SessionInfoStorage {
|
||||||
return Promise.resolve([]);
|
return Promise.resolve([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateLastUsed(id, timestamp) {
|
async updateLastUsed(id: string, timestamp: number): Promise<void> {
|
||||||
const sessions = await this.getAll();
|
const sessions = await this.getAll();
|
||||||
if (sessions) {
|
if (sessions) {
|
||||||
const session = sessions.find(session => session.id === id);
|
const session = sessions.find(session => session.id === id);
|
||||||
|
@ -41,20 +62,20 @@ export class SessionInfoStorage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(id) {
|
async get(id: string): Promise<ISessionInfo | undefined> {
|
||||||
const sessions = await this.getAll();
|
const sessions = await this.getAll();
|
||||||
if (sessions) {
|
if (sessions) {
|
||||||
return sessions.find(session => session.id === id);
|
return sessions.find(session => session.id === id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async add(sessionInfo) {
|
async add(sessionInfo: ISessionInfo): Promise<void> {
|
||||||
const sessions = await this.getAll();
|
const sessions = await this.getAll();
|
||||||
sessions.push(sessionInfo);
|
sessions.push(sessionInfo);
|
||||||
localStorage.setItem(this._name, JSON.stringify(sessions));
|
localStorage.setItem(this._name, JSON.stringify(sessions));
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(sessionId) {
|
async delete(sessionId: string): Promise<void> {
|
||||||
let sessions = await this.getAll();
|
let sessions = await this.getAll();
|
||||||
sessions = sessions.filter(s => s.id !== sessionId);
|
sessions = sessions.filter(s => s.id !== sessionId);
|
||||||
localStorage.setItem(this._name, JSON.stringify(sessions));
|
localStorage.setItem(this._name, JSON.stringify(sessions));
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||||
import {createFetchRequest} from "./dom/request/fetch.js";
|
import {createFetchRequest} from "./dom/request/fetch.js";
|
||||||
import {xhrRequest} from "./dom/request/xhr.js";
|
import {xhrRequest} from "./dom/request/xhr.js";
|
||||||
import {StorageFactory} from "../../matrix/storage/idb/StorageFactory";
|
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 {SettingsStorage} from "./dom/SettingsStorage.js";
|
||||||
import {Encoding} from "./utils/Encoding.js";
|
import {Encoding} from "./utils/Encoding.js";
|
||||||
import {OlmWorker} from "../../matrix/e2ee/OlmWorker.js";
|
import {OlmWorker} from "../../matrix/e2ee/OlmWorker.js";
|
||||||
|
|
Loading…
Reference in a new issue