From bf1fd7ce6b0572ba20cfcbebe957aa9c6b74a0a2 Mon Sep 17 00:00:00 2001 From: NI Date: Sat, 26 Dec 2020 17:58:32 +0800 Subject: [PATCH] Preset: Only save session data (credentials etc) to `localStorage` when the those data is defined by the Preset. This is so we don't accidentally save user secrets into `localStorage` --- ui/commands/commands.js | 22 ++++++++---- ui/commands/history.js | 74 +++++++++++++++++++++++++++++++++-------- ui/commands/presets.js | 16 +++++++++ ui/commands/ssh.js | 65 +++++++++++++++++++++++++++--------- ui/commands/telnet.js | 38 ++++++++++++++------- ui/home.vue | 4 +-- 6 files changed, 168 insertions(+), 51 deletions(-) diff --git a/ui/commands/commands.js b/ui/commands/commands.js index 1a11beb..21de7ad 100644 --- a/ui/commands/commands.js +++ b/ui/commands/commands.js @@ -219,17 +219,25 @@ export function fields(definitions, fs) { * @param {object} definitions Definition of a group of fields * @param {object} fieldsData field data object, formated like a `defField` * @param {presets.Preset} presetData Preset data + * @param {function} presetApplied Called when a preset is used for a field * * @returns {object} * */ -export function fieldsWithPreset(definitions, fieldsData, presetData) { +export function fieldsWithPreset( + definitions, + fieldsData, + presetData, + presetApplied +) { let newFields = fields(definitions, fieldsData); for (let i in newFields) { try { newFields[i].value = presetData.meta(newFields[i].name); newFields[i].readonly = true; + + presetApplied(newFields[i].name); } catch (e) { // Do nothing } @@ -685,13 +693,13 @@ class Builder { * @param {history.History} history * @param {presets.Preset} preset * @param {object} session - * @param {boolean} keepSession + * @param {Array} keptSessions * @param {function} done Callback which will be called when wizard is done * * @returns {Wizard} Command wizard * */ - wizard(streams, controls, history, preset, session, keepSession, done) { + wizard(streams, controls, history, preset, session, keptSessions, done) { let subs = new subscribe.Subscribe(); return new Wizard( @@ -699,7 +707,7 @@ class Builder { new Info(this), preset, session, - keepSession, + keptSessions, streams, subs, controls, @@ -718,13 +726,13 @@ class Builder { * @param {history.History} history * @param {object} config * @param {object} session - * @param {boolean} saveSession + * @param {Array} keptSessions * @param {function} done Callback which will be called when wizard is done * * @returns {Wizard} Command wizard * */ - execute(streams, controls, history, config, session, saveSession, done) { + execute(streams, controls, history, config, session, keptSessions, done) { let subs = new subscribe.Subscribe(); return new Wizard( @@ -732,7 +740,7 @@ class Builder { new Info(this), config, session, - saveSession, + keptSessions, streams, subs, controls, diff --git a/ui/commands/history.js b/ui/commands/history.js index 735a697..7afe099 100644 --- a/ui/commands/history.js +++ b/ui/commands/history.js @@ -17,6 +17,46 @@ import * as command from "./commands.js"; +/** + * Extract needed data + * + * @param {Array} kept The keys of of the data to be kept + * @param {object} input Input data + * + * @return {object} Extracted data + */ +function extractSelectedData(kept, input) { + if (!kept || typeof kept !== "object" || kept.length < 0) { + return null; + } + + let data = {}, + length = 0; + + for (let k in kept) { + if (!input[kept[k]]) { + continue; + } + + data[kept[k]] = input[kept[k]]; + length++; + } + + if (length <= 0) { + return null; + } + + return data; +} + +/** + * constructor + * + * @param {object} data to be searched + * @param {string} metaName name of the meta + * @param {string} valContains target string to search + * + */ function metaContains(data, metaName, valContains) { switch (typeof data[metaName]) { case "string": @@ -31,7 +71,7 @@ export class History { /** * constructor * - * @param {array} records + * @param {Array} records * @param {function} saver * @param {number} maxItems * @@ -71,11 +111,11 @@ export class History { * @param {Date} lastUsed Last used * @param {object} data Data * @param {object} sessionData Data which only available for current session - * @param {boolean} keepSession Whether or not to keep session data when - * putting the item to the persistent storage + * @param {Array} keptSessions Keys of the session data that should + * be saved * */ - save(uname, title, lastUsed, info, data, sessionData, keepSession) { + save(uname, title, lastUsed, info, data, sessionData, keptSessions) { const unameIdx = this.indexOf(uname); if (unameIdx >= 0) { @@ -90,7 +130,7 @@ export class History { last: lastUsed.getTime(), data: data, session: sessionData, - keepSession: keepSession, + keptSessions: keptSessions, }); if (this.records.length > this.maxItems) { @@ -143,7 +183,7 @@ export class History { } this.records[i].session = null; - this.records[i].keepSession = false; + this.records[i].keptSessions = []; break; } @@ -154,7 +194,7 @@ export class History { * Return all history records. The exported data is differ than the * internal ones, it cannot be directly import back * - * @returns {array} Records + * @returns {Array} Records * */ all() { @@ -169,7 +209,7 @@ export class History { last: new Date(this.records[i].last), data: this.records[i].data, session: this.records[i].session, - keepSession: this.records[i].keepSession, + keptSessions: this.records[i].keptSessions, }); } @@ -179,7 +219,7 @@ export class History { /** * Export current history records * - * @returns {array} Records + * @returns {Array} Records * */ export() { @@ -193,8 +233,11 @@ export class History { color: this.records[i].color, last: this.records[i].last, data: this.records[i].data, - session: this.records[i].keepSession ? this.records[i].session : null, - keepSession: this.records[i].keepSession, + session: extractSelectedData( + this.records[i].keptSessions, + this.records[i].session + ), + keptSessions: this.records[i].keptSessions, }); } @@ -204,7 +247,7 @@ export class History { /** * Import data into current history records * - * @param {array} records Records + * @param {Array} records Records * */ import(records) { @@ -220,8 +263,11 @@ export class History { color: records[i].color, last: records[i].last, data: records[i].data, - session: records[i].session, - keepSession: records[i].keepSession, + session: extractSelectedData( + records[i].keptSessions, + records[i].session + ), + keptSessions: records[i].keptSessions, }); } diff --git a/ui/commands/presets.js b/ui/commands/presets.js index c95d2aa..982e046 100644 --- a/ui/commands/presets.js +++ b/ui/commands/presets.js @@ -188,6 +188,22 @@ export class Preset { this.preset.meta[name] = data; } + + /** + * Export all meta keys + * + * @returns {Array} All meta keys + * + */ + metaKeys() { + let keys = []; + + for (let k in this.preset.meta) { + keys.push(k); + } + + return keys; + } } /** diff --git a/ui/commands/ssh.js b/ui/commands/ssh.js index 2d2753c..e89848b 100644 --- a/ui/commands/ssh.js +++ b/ui/commands/ssh.js @@ -505,18 +505,18 @@ class Wizard { * @param {command.Info} info * @param {presets.Preset} preset * @param {object} session + * @param {Array} keptSessions * @param {streams.Streams} streams * @param {subscribe.Subscribe} subs * @param {controls.Controls} controls * @param {history.History} history - * @param {boolean} saveSession * */ constructor( info, preset, session, - saveSession, + keptSessions, streams, subs, controls, @@ -531,7 +531,7 @@ class Wizard { : { credential: "", }; - this.saveSession = saveSession; + this.keptSessions = keptSessions; this.step = subs; this.controls = controls.get("SSH"); this.history = history; @@ -611,6 +611,9 @@ class Wizard { fingerprint: configInput.fingerprint, }; + // Copy the keptSessions from the record so it will not be overwritten here + let keptSessions = self.keptSessions ? [].concat(...self.keptSessions) : []; + return new SSH(sender, config, { "initialization.failed"(hd) { switch (hd.data()) { @@ -680,7 +683,7 @@ class Wizard { self.info, configInput, sessionData, - self.saveSession + keptSessions ); }, async "connect.fingerprint"(rd, sd) { @@ -707,8 +710,13 @@ class Wizard { }, async "connect.credential"(rd, sd) { self.step.resolve( - self.stepCredentialPrompt(rd, sd, config, (newCredential) => { - sessionData.credential = newCredential; + self.stepCredentialPrompt(rd, sd, config, (newCred, fromPreset) => { + sessionData.credential = newCred; + + // Save the credential if the credential was from a preset + if (fromPreset && keptSessions.indexOf("credential") < 0) { + keptSessions.push("credential"); + } }) ); }, @@ -790,7 +798,8 @@ class Wizard { { name: "Encoding" }, { name: "Notice" }, ], - self.preset + self.preset, + (r) => {} ) ); } @@ -873,6 +882,20 @@ class Wizard { ); } + let presetCredentialUsed = false; + const inputFields = command.fieldsWithPreset( + initialFieldDef, + fields, + self.preset, + (r) => { + if (r !== fields[0].name) { + return; + } + + presetCredentialUsed = true; + } + ); + return command.prompt( "Provide credential", "Please input your credential", @@ -885,7 +908,7 @@ class Wizard { new TextEncoder().encode(vv) ); - newCredential(vv); + newCredential(vv, presetCredentialUsed); self.step.resolve(self.stepContinueWaitForEstablishWait()); }, @@ -899,7 +922,7 @@ class Wizard { ) ); }, - command.fieldsWithPreset(initialFieldDef, fields, self.preset) + inputFields ); } } @@ -911,7 +934,7 @@ class Executer extends Wizard { * @param {command.Info} info * @param {config} config * @param {object} session - * @param {boolean} saveSession + * @param {Array} keptSessions * @param {streams.Streams} streams * @param {subscribe.Subscribe} subs * @param {controls.Controls} controls @@ -922,7 +945,7 @@ class Executer extends Wizard { info, config, session, - saveSession, + keptSessions, streams, subs, controls, @@ -932,7 +955,7 @@ class Executer extends Wizard { info, presets.emptyPreset(), session, - saveSession, + keptSessions, streams, subs, controls, @@ -984,12 +1007,21 @@ export class Command { return "#3c8"; } - wizard(info, preset, session, saveSession, streams, subs, controls, history) { + wizard( + info, + preset, + session, + keptSessions, + streams, + subs, + controls, + history + ) { return new Wizard( info, preset, session, - saveSession, + keptSessions, streams, subs, controls, @@ -1001,7 +1033,7 @@ export class Command { info, config, session, - saveSession, + keptSessions, streams, subs, controls, @@ -1011,7 +1043,7 @@ export class Command { info, config, session, - saveSession, + keptSessions, streams, subs, controls, @@ -1057,6 +1089,7 @@ export class Command { charset: charset, }, null, + null, streams, subs, controls, diff --git a/ui/commands/telnet.js b/ui/commands/telnet.js index 3c2b6e5..0751457 100644 --- a/ui/commands/telnet.js +++ b/ui/commands/telnet.js @@ -247,7 +247,7 @@ class Wizard { * @param {command.Info} info * @param {presets.Preset} preset * @param {object} session - * @param {boolean} saveSession + * @param {Array} keptSessions * @param {streams.Streams} streams * @param {subscribe.Subscribe} subs * @param {controls.Controls} controls @@ -258,7 +258,7 @@ class Wizard { info, preset, session, - saveSession, + keptSessions, streams, subs, controls, @@ -269,7 +269,7 @@ class Wizard { this.hasStarted = false; this.streams = streams; this.session = session; - this.saveSession = saveSession; + this.keptSessions = keptSessions; this.step = subs; this.controls = controls.get("Telnet"); this.history = history; @@ -338,6 +338,9 @@ class Wizard { charset: configInput.charset, }; + // Copy the keptSessions from the record so it will not be overwritten here + let keptSessions = self.keptSessions ? [].concat(...self.keptSessions) : []; + return new Telnet(sender, parsedConfig, { "initialization.failed"(streamInitialHeader) { switch (streamInitialHeader.data()) { @@ -387,7 +390,7 @@ class Wizard { self.info, configInput, sessionData, - self.saveSession + keptSessions ); }, async "connect.failed"(rd) { @@ -456,7 +459,8 @@ class Wizard { }, { name: "Encoding" }, ], - self.preset + self.preset, + (r) => {} ) ); } @@ -469,7 +473,7 @@ class Executor extends Wizard { * @param {command.Info} info * @param {object} config * @param {object} session - * @param {boolean} saveSession + * @param {Array} keptSessions * @param {streams.Streams} streams * @param {subscribe.Subscribe} subs * @param {controls.Controls} controls @@ -480,7 +484,7 @@ class Executor extends Wizard { info, config, session, - saveSession, + keptSessions, streams, subs, controls, @@ -490,7 +494,7 @@ class Executor extends Wizard { info, presets.emptyPreset(), session, - saveSession, + keptSessions, streams, subs, controls, @@ -539,12 +543,21 @@ export class Command { return "#6ac"; } - wizard(info, preset, session, saveSession, streams, subs, controls, history) { + wizard( + info, + preset, + session, + keptSessions, + streams, + subs, + controls, + history + ) { return new Wizard( info, preset, session, - saveSession, + keptSessions, streams, subs, controls, @@ -556,7 +569,7 @@ export class Command { info, config, session, - saveSession, + keptSessions, streams, subs, controls, @@ -566,7 +579,7 @@ export class Command { info, config, session, - saveSession, + keptSessions, streams, subs, controls, @@ -611,6 +624,7 @@ export class Command { charset: charset, }, null, + null, streams, subs, controls, diff --git a/ui/home.vue b/ui/home.vue index 12a8b93..8d57d7e 100644 --- a/ui/home.vue +++ b/ui/home.vue @@ -366,7 +366,7 @@ export default { self.connector.historyRec, preset.preset, null, - true, + [], () => {} ), }; @@ -411,7 +411,7 @@ export default { self.connector.historyRec, known.data, known.session, - known.keepSession, + known.keptSessions, () => { self.connector.knowns = self.connector.historyRec.all(); }