From a4756007a5bc897203972db579485ddb17830320 Mon Sep 17 00:00:00 2001 From: Giuseppe Stelluto Date: Sun, 21 Jan 2024 17:10:19 +0100 Subject: [PATCH] Refactor LoginWithQR to use LoginHandler --- src/Login.tsx | 5 +- src/LoginWithQR/LoginWithQR.tsx | 136 ++++++++++---------------------- 2 files changed, 46 insertions(+), 95 deletions(-) diff --git a/src/Login.tsx b/src/Login.tsx index 7f51b94..b14c063 100644 --- a/src/Login.tsx +++ b/src/Login.tsx @@ -121,7 +121,8 @@ class Login extends Component<{}, LoginState> { render() { if (this.state.loginWithQr) { - return ; + return ; + // return ; } let listViewChildren; switch (this.state.stage) { @@ -147,7 +148,7 @@ class Login extends Component<{}, LoginState> { }, { tertiary: - "Press Call button and scan a QR in the following format to login with QR code instead of typing all these(PASS = password authentication): PASS server_name username password", + "Press Call button and scan a QR in the following format to login with QR code instead of typing all these (PASS = password authentication): PASS server_name username password", type: "text", key: "qrHint", }, diff --git a/src/LoginWithQR/LoginWithQR.tsx b/src/LoginWithQR/LoginWithQR.tsx index b7ba8eb..f6ea2ae 100644 --- a/src/LoginWithQR/LoginWithQR.tsx +++ b/src/LoginWithQR/LoginWithQR.tsx @@ -1,16 +1,18 @@ import { Component } from "inferno"; import QrScanner from "qr-scanner"; -import { createClient } from "matrix-js-sdk"; -import * as localforage from "localforage"; +import { LoginFlow } from "matrix-js-sdk/lib/@types/auth"; import "./LoginWithQR.css"; import { SoftKey } from "KaiUI"; -import shared from "../shared"; -import { fetch as customFetch } from "../fetch"; -import { WellKnown } from "../types"; +import LoginHandler from "../LoginHandler"; -class LoginWithQR extends Component<{}, {}> { +interface LoginWithQRProps { + loginHandler: LoginHandler; +} + +class LoginWithQR extends Component { private video?: HTMLVideoElement; + private loginHandler: LoginHandler; startScanning = () => { if (!this.video) { @@ -27,104 +29,52 @@ class LoginWithQR extends Component<{}, {}> { scanner.start(); }; - doLogin = (data: string) => { + private login_flows_short: {[key: string]: string} = { + "PASS": "m.login.password" + } + + private async doLogin (data: string) { let decodedParts: string[] = data.split(" ", 4); - const flow = decodedParts[0]; + let flow = decodedParts[0]; const server_name = decodedParts[1]; const username = decodedParts[2]; - let password: string; - if ( - window.confirm( - `Do you confirm? Flow: ${flow} | Server name: ${server_name} | Username: ${username}` - ) - ) { - const start: number = - flow.length + server_name.length + username.length + 3; - password = data.substring(start); - fetch(`https://${server_name}/.well-known/matrix/client`).then( - (r: Response) => { - if (r.ok) { - r.json() - .then((j: WellKnown) => { - const server_url: string = j["m.homeserver"].base_url; - shared.mClient = createClient({ - baseUrl: server_url, - fetchFn: customFetch, - }); - shared.mClient - .loginFlows() - .then((result) => { - let gotPasswordLogin = false; - for (let flow of result.flows) { - if ("m.login.password" === flow.type) { - gotPasswordLogin = true; - break; - } - } - if (gotPasswordLogin) { - shared.mClient - .loginWithPassword( - `@${username}:${server_name}`, - password - ) - .then((result: any) => { - localforage.setItem("login", result).then(() => { - window.alert("Logged in as " + username); - window.location = window.location; - }); - }) - .catch((err: any) => { - switch (err.errcode) { - case "M_FORBIDDEN": - alert("Incorrect login credentials"); - break; - case "M_USER_DEACTIVATED": - alert("This account has been deactivated"); - break; - case "M_LIMIT_EXCEEDED": - const retry = Math.ceil( - err.retry_after_ms / 1000 - ); - alert( - "Too many requests! Retry after" + - retry.toString() - ); - break; - default: - alert("Login failed! Unknown reason"); - break; - } - // eslint-disable-next-line no-self-assign - window.location = window.location; - }); - } else { - window.alert( - "This homeserver does not support authentication with password" - ); - } - }) - .catch((e) => { - window.alert("Error getting login flows from the server"); - console.log(e); - }); - }) - .catch((e) => { - window.alert("Error getting information about the server"); - console.log("REPORT", e); - }); - } else { - alert( - "Cannot connect to homeserver. Are you sure the address is correct?" - ); + const start = flow.length + server_name.length + username.length + 3; + let password: string = data.substring(start); + // TODO implement more flows + if (window.confirm( + `Do you confirm? Flow: ${flow} | Server name: ${server_name} | Username: ${username}`)) { + // users can either write the full m.login.password (or whatever other flow) or use a shorthand + // This maps the shorthand to the actual flow identificator + if (!flow.startsWith("m.login")) { + flow = this.login_flows_short[flow]; + } + if (flow !== "m.login.password") { + alert("Password authentication is the only supported flow currently") + return; + } + try { + await this.loginHandler.findHomeserver(server_name); + let selected_flow: LoginFlow | undefined; + for (let available_flow of this.loginHandler.loginFlows) { + if (available_flow.type === flow) { + selected_flow = available_flow; } } - ); + if (selected_flow !== undefined) { + let loginData = {'username': username, 'password': password}; + await this.loginHandler.doLogin(selected_flow, loginData); + window.location = window.location; + } + } catch (e) { + alert(e) + } } }; constructor(props: any) { super(props); this.state = null; + this.loginHandler = props.loginHandler; } componentDidMount() {