'use strict'; const React = require('react'); const ReactDOM = require('react-dom'); const create = require('create-react-class'); const Promise = require('bluebird'); const urllib = require('url'); const debounce = require('debounce'); const defaultValue = require('default-value'); let login = create({ displayName: "Login", getInitialState: function() { return { error: null, formState: { user: "", pass: "", hs: "" }, hs: { prompt: false, error: null, valid: false } }; }, login: function() { this.setState({error: ""}); if (this.state.hs.valid) { return this.doLogin(); } let parts = this.state.formState.user.split(':'); if (parts.length != 2) { return this.setState({error: "Please enter a full mxid, like username:homeserver.tld"}); } let hostname = urllib.parse("https://" + parts[1]); getApiServer(hostname).then((hs) => { console.log("Using API server", hs); let formState = this.state.formState; formState.user = parts[0]; formState.hs = hs; let hsState = Object.assign(this.state.hs, {valid: true}); this.setState({apiUrl: hs, formState: formState, hs: hsState}); this.doLogin(); }).catch((error) => { console.log("ERROR fetching homeserver url", error); let hsState = Object.assign(this.state.hs, {error: error, valid: false, prompt: true}); this.setState({hs: hsState}); }); }, doLogin: function() { console.log("Logging in"); let user = this.state.formState.user.replace('@', ''); let password = this.state.formState.pass; let hs = this.state.apiUrl; let data = { user: user, password: password, type: "m.login.password", initial_device_display_name: "Neo v4", }; let url = hs + "/_matrix/client/r0/login"; fetch(url, { body: JSON.stringify(data), headers: { 'content-type': 'application/json' }, method: 'POST', }).then((response) => response.json()) .then((responseJson) => { console.log("got access token", responseJson); this.setState({json: responseJson}); if(responseJson.access_token != undefined) { this.props.callback(responseJson.user_id, responseJson.access_token, hs); } else { this.setState({error: responseJson.error}); } }) .catch((error) => { console.error(url, error); }); }, handleUserChange: function(e) { let formState = this.state.formState; let user = e.target.value; formState.user = e.target.value; let parts = user.split(':'); if (parts.length == 2) { formState.hs = parts[1]; let hsState = Object.assign(this.state.hs, {error: null, valid: false}); this.setState({hs: hsState}); } this.setState({formState: formState}); }, handlePassChange: function(e) { let formState = this.state.formState; formState.pass = e.target.value; this.setState({formState: formState}); }, handleHsChange: function(e) { let formState = this.state.formState; formState.hs = e.target.value; this.setState({formState: formState}); this.setState({hs: {error: null, valid: false, prompt: true, changed: true}}); }, render: function() { let hsState = "inactive"; if (this.state.hs.prompt) { hsState = "active"; } if (this.state.hs.error != null) { hsState = "error"; } if (this.state.hs.valid) { hsState = "validated"; } return (
{this.state.error}
{this.state.hs.prompt ? ( <> ) : ( {this.state.formState["hs"]} )}
); } }); function getApiServer(hostname) { return new Promise((resolve, reject) => { console.log("Checking for api server from mxid", urllib.format(hostname)); checkApi(hostname).then(() => { // Hostname is a valid api server hostname.pathname = ""; resolve(urllib.format(hostname)); }).catch(() => { console.log("trying .well-known"); tryWellKnown(hostname).then((hostname) => { console.log("got .well-known host", hostname); resolve(hostname); }).catch((err) => { reject("Fatal error trying to get API host"); }); }); }); } function checkApi(host) { let versionUrl = buildUrl(host, "/_matrix/client/versions"); return new Promise((resolve, reject) => { fetch(versionUrl).then((response) => { if (response.status != 200) { console.log("Invalid homeserver url", versionUrl); return reject(); } resolve(); }).catch((err) => { reject(err); }); }); } function tryWellKnown(host) { let wellKnownUrl = urllib.format(Object.assign(host, { pathname: "/.well-known/matrix/client" })); console.log("Trying", wellKnownUrl, "for .well-known"); return new Promise((resolve, reject) => { return fetch(wellKnownUrl) .then((response) => { if (response.status != 200) { console.log("no well-known in use"); reject("No homeserver found"); } return response; }).catch((error) => { reject("can't fetch .well-known"); }) .then((response) => response.json()) .then((json) => { console.log("Parsed json", json); if (json['m.homeserver'] != undefined && json['m.homeserver'].base_url != undefined) { resolve(json['m.homeserver'].base_url); } }) .catch((err) => { console.log("Error in json", err); reject("Error while parsing .well-known"); }); }); } function buildUrl(host, path) { return urllib.format(Object.assign(host, { pathname: path })); } module.exports = login;