store all logout data outside of the session storage

so we could store it in gnome keyring, macOs keychain, ... on non-webclients,
also better separation
This commit is contained in:
Bruno Windels 2019-03-08 20:00:37 +01:00
parent 2dbd0fb9dc
commit 994f1c57d3
2 changed files with 36 additions and 36 deletions

View file

@ -11,50 +11,61 @@ const USERNAME = "bruno1";
const USER_ID = `@${USERNAME}:${HOST}`; const USER_ID = `@${USERNAME}:${HOST}`;
const PASSWORD = "testtest"; const PASSWORD = "testtest";
function getSessionId(userId) { function getSessionInfo(userId) {
const sessionsJson = localStorage.getItem("morpheus_sessions_v1"); const sessionsJson = localStorage.getItem("morpheus_sessions_v1");
if (sessionsJson) { if (sessionsJson) {
const sessions = JSON.parse(sessionsJson); const sessions = JSON.parse(sessionsJson);
const session = sessions.find(session => session.userId === userId); const session = sessions.find(session => session.userId === userId);
if (session) { if (session) {
return session.id; return session;
} }
} }
} }
function storeSessionInfo(loginData) {
const sessionsJson = localStorage.getItem("morpheus_sessions_v1");
const sessions = sessionsJson ? JSON.parse(sessionsJson) : [];
const sessionId = (Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)).toString();
const sessionInfo = {
id: sessionId,
deviceId: loginData.device_id,
userId: loginData.user_id,
homeServer: loginData.home_server,
accessToken: loginData.access_token,
};
sessions.push(sessionInfo);
localStorage.setItem("morpheus_sessions_v1", JSON.stringify(sessions));
return sessionInfo;
}
async function login(username, password, homeserver) { async function login(username, password, homeserver) {
const hsApi = new HomeServerApi(homeserver); const hsApi = new HomeServerApi(homeserver);
const loginData = await hsApi.passwordLogin(username, password).response(); const loginData = await hsApi.passwordLogin(username, password).response();
const sessionsJson = localStorage.getItem("morpheus_sessions_v1"); return storeSessionInfo(loginData);
const sessions = sessionsJson ? JSON.parse(sessionsJson) : [];
const sessionId = (Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)).toString();
console.log(loginData);
sessions.push({userId: loginData.user_id, id: sessionId});
localStorage.setItem("morpheus_sessions_v1", JSON.stringify(sessions));
return {sessionId, loginData};
} }
function showSession(container, session) { function showSession(container, session) {
const vm = new SessionViewModel(session); const vm = new SessionViewModel(session);
const view = new SessionView(vm); const view = new SessionView(vm);
container.appendChild(view.mount()); view.mount();
container.appendChild(view.root());
} }
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
export default async function main(label, button, container) { export default async function main(label, button, container) {
try { try {
let sessionId = getSessionId(USER_ID); let sessionInfo = getSessionInfo(USER_ID);
let loginData; if (!sessionInfo) {
if (!sessionId) { sessionInfo = await login(USERNAME, PASSWORD, HOMESERVER);
({sessionId, loginData} = await login(USERNAME, PASSWORD, HOMESERVER));
} }
const storage = await createIdbStorage(`morpheus_session_${sessionId}`); const storage = await createIdbStorage(`morpheus_session_${sessionInfo.id}`);
const session = new Session(storage); const hsApi = new HomeServerApi(HOMESERVER, sessionInfo.accessToken);
if (loginData) { const session = new Session({storage, hsApi, sessionInfo: {
await session.setLoginData(loginData); deviceId: sessionInfo.deviceId,
} userId: sessionInfo.userId,
await session.load(); homeServer: sessionInfo.homeServer, //only pass relevant fields to Session
const hsApi = new HomeServerApi(HOMESERVER, session.accessToken); }});
await session.load();
console.log("session loaded"); console.log("session loaded");
const needsInitialSync = !session.syncToken; const needsInitialSync = !session.syncToken;
if (needsInitialSync) { if (needsInitialSync) {

View file

@ -2,21 +2,13 @@ import Room from "./room/room.js";
import { ObservableMap } from "../observable/index.js"; import { ObservableMap } from "../observable/index.js";
export default class Session { export default class Session {
constructor(storage) { constructor({storage, sessionInfo}) {
this._storage = storage; this._storage = storage;
this._session = null; this._session = null;
this._sessionInfo = sessionInfo;
this._rooms = new ObservableMap(); this._rooms = new ObservableMap();
this._roomUpdateCallback = (room, params) => this._rooms.update(room.id, params); this._roomUpdateCallback = (room, params) => this._rooms.update(room.id, params);
} }
// should be called before load
// loginData has device_id, user_id, home_server, access_token
async setLoginData(loginData) {
console.log("session.setLoginData");
const txn = await this._storage.readWriteTxn([this._storage.storeNames.session]);
const session = {loginData};
txn.session.set(session);
await txn.complete();
}
async load() { async load() {
const txn = await this._storage.readTxn([ const txn = await this._storage.readTxn([
@ -28,7 +20,8 @@ export default class Session {
// restore session object // restore session object
this._session = await txn.session.get(); this._session = await txn.session.get();
if (!this._session) { if (!this._session) {
throw new Error("session store is empty"); this._session = {};
return;
} }
// load rooms // load rooms
const rooms = await txn.roomSummary.getAll(); const rooms = await txn.roomSummary.getAll();
@ -58,8 +51,4 @@ export default class Session {
get syncToken() { get syncToken() {
return this._session.syncToken; return this._session.syncToken;
} }
get accessToken() {
return this._session.loginData.access_token;
}
} }