import * as sdk from 'matrix-js-sdk'; import cons from '../state/cons'; import { getBaseUrl } from '../../util/matrixUtil'; async function login(username, homeserver, password) { let baseUrl = null; try { baseUrl = await getBaseUrl(homeserver); } catch (e) { baseUrl = `https://${homeserver}`; } if (typeof baseUrl === 'undefined') throw new Error('Homeserver not found'); const client = sdk.createClient({ baseUrl }); const response = await client.login('m.login.password', { user: `@${username}:${homeserver}`, password, initial_device_display_name: cons.DEVICE_DISPLAY_NAME, }); localStorage.setItem(cons.secretKey.ACCESS_TOKEN, response.access_token); localStorage.setItem(cons.secretKey.DEVICE_ID, response.device_id); localStorage.setItem(cons.secretKey.USER_ID, response.user_id); localStorage.setItem(cons.secretKey.BASE_URL, response?.well_known?.['m.homeserver']?.base_url || baseUrl); } async function getAdditionalInfo(baseUrl, content) { try { const res = await fetch(`${baseUrl}/_matrix/client/r0/register`, { method: 'POST', body: JSON.stringify(content), headers: { 'Content-Type': 'application/json; charset=utf-8', }, credentials: 'same-origin', }); const data = await res.json(); return data; } catch (e) { throw new Error(e); } } async function verifyEmail(baseUrl, content) { try { const res = await fetch(`${baseUrl}/_matrix/client/r0/register/email/requestToken `, { method: 'POST', body: JSON.stringify(content), headers: { 'Content-Type': 'application/json; charset=utf-8', }, credentials: 'same-origin', }); const data = await res.json(); return data; } catch (e) { throw new Error(e); } } let session = null; let clientSecret = null; let sid = null; async function register(username, homeserver, password, email, recaptchaValue, terms, verified) { const baseUrl = await getBaseUrl(homeserver); if (typeof baseUrl === 'undefined') throw new Error('Homeserver not found'); const client = sdk.createClient({ baseUrl }); const isAvailable = await client.isUsernameAvailable(username); if (!isAvailable) throw new Error('Username not available'); if (typeof recaptchaValue === 'string') { await getAdditionalInfo(baseUrl, { auth: { type: 'm.login.recaptcha', session, response: recaptchaValue, }, }); } else if (terms === true) { await getAdditionalInfo(baseUrl, { auth: { type: 'm.login.terms', session, }, }); } else if (verified !== true) { session = null; clientSecret = client.generateClientSecret(); const verifyData = await verifyEmail(baseUrl, { email, client_secret: clientSecret, send_attempt: 1, }); if (typeof verifyData.error === 'string') { throw new Error(verifyData.error); } sid = verifyData.sid; } const additionalInfo = await getAdditionalInfo(baseUrl, { auth: { session: (session !== null) ? session : undefined }, }); session = additionalInfo.session; if (typeof additionalInfo.completed === 'undefined' || additionalInfo.completed.length === 0) { return ({ type: 'recaptcha', public_key: additionalInfo.params['m.login.recaptcha'].public_key, }); } if (additionalInfo.completed.find((process) => process === 'm.login.recaptcha') === 'm.login.recaptcha' && !additionalInfo.completed.find((process) => process === 'm.login.terms')) { return ({ type: 'terms', en: additionalInfo.params['m.login.terms'].policies.privacy_policy.en, }); } if (verified || additionalInfo.completed.find((process) => process === 'm.login.terms') === 'm.login.terms') { const tpc = { client_secret: clientSecret, sid, }; const verifyData = await getAdditionalInfo(baseUrl, { auth: { session, type: 'm.login.email.identity', threepidCreds: tpc, threepid_creds: tpc, }, username, password, }); if (verifyData.errcode === 'M_UNAUTHORIZED') { return { type: 'email' }; } localStorage.setItem(cons.secretKey.ACCESS_TOKEN, verifyData.access_token); localStorage.setItem(cons.secretKey.DEVICE_ID, verifyData.device_id); localStorage.setItem(cons.secretKey.USER_ID, verifyData.user_id); localStorage.setItem(cons.secretKey.BASE_URL, baseUrl); return { type: 'done' }; } return {}; } export { login, register };