Merge branch 'ICU-1335-close-session-on-cancel' into ICU-1335-close-all-sessions-on-exit
This commit is contained in:
10 files changed
+66
-69
No files matched your search
@@ -84,6 +84,6 @@ export default class ScopesScopeProjectsSessionsRoute extends Route {
|
||||
@notifySuccess('notifications.canceled-success')
|
||||
async cancelSession(session) {
|
||||
await session.cancelSession();
|
||||
await this.ipc.invoke('cancel', { session_id: session.id });
|
||||
await this.ipc.invoke('stop', { session_id: session.id });
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,6 @@ export default class ScopesScopeProjectsTargetsTargetSessionsRoute extends Route
|
||||
@notifySuccess('notifications.canceled-success')
|
||||
async cancelSession(session) {
|
||||
await session.cancelSession();
|
||||
await this.ipc.invoke('cancel', { session_id: session.id });
|
||||
await this.ipc.invoke('stop', { session_id: session.id });
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ module.exports = {
|
||||
outputStream += data.toString();
|
||||
const jsonData = jsonify(outputStream);
|
||||
if (jsonData) {
|
||||
childProcess.removeListener('data', processData);
|
||||
childProcess.removeAllListeners();
|
||||
resolve({ childProcess, response: jsonData });
|
||||
}
|
||||
};
|
||||
@@ -50,12 +50,12 @@ module.exports = {
|
||||
const jsonData = jsonify(errorStream);
|
||||
if (jsonData) {
|
||||
const error = jsonData.api_error || jsonData.error;
|
||||
childProcess.removeListener('error', processError);
|
||||
childProcess.removeAllListeners();
|
||||
reject(new Error(error.message));
|
||||
}
|
||||
};
|
||||
|
||||
childProcess.stderr.on('data', processError);
|
||||
childProcess.stderr.on('error', processError);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -61,4 +61,4 @@ handle('connect', ({ target_id, token, host_id }) =>
|
||||
/**
|
||||
* Cancel an established boundary session spawned process.
|
||||
*/
|
||||
handle('cancel', ({ session_id }) => sessionManager.stopById(session_id));
|
||||
handle('stop', ({ session_id }) => sessionManager.stopById(session_id));
|
||||
@@ -0,0 +1,33 @@
|
||||
const Session = require('./session.js');
|
||||
|
||||
class SessionManager {
|
||||
#sessions = [];
|
||||
|
||||
/**
|
||||
* Start a session and track it.
|
||||
* Returns session proxy details if successfully started.
|
||||
* @param {string} addr
|
||||
* @param {string} target_id
|
||||
* @param {string} token
|
||||
* @param {string} host_id
|
||||
*/
|
||||
start(addr, target_id, token, host_id) {
|
||||
const session = new Session(addr, target_id, token, host_id);
|
||||
this.#sessions.push(session);
|
||||
return session.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a session using identifier.
|
||||
* @param {string} session_id
|
||||
*/
|
||||
stopById(session_id) {
|
||||
const session = this.#sessions.find((session) => session.id === session_id);
|
||||
return session.stop();
|
||||
}
|
||||
|
||||
stopAll() {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SessionManager;
|
||||
+6
-16
@@ -1,16 +1,5 @@
|
||||
const { spawnAsyncJSONPromise } = require('../helpers/spawn-promise.js');
|
||||
/**
|
||||
* Super paranoid shell quote/escape and validation. Input must be base62.
|
||||
* @param {string} str
|
||||
*/
|
||||
const escapeAndValidateBase62 = (str) => {
|
||||
const candidate = str.toString();
|
||||
if (candidate.match(/^[A-Za-z0-9_]*$/)) return candidate;
|
||||
throw new Error(`
|
||||
Could not invoke command:
|
||||
input contained unsafe characters.
|
||||
`);
|
||||
};
|
||||
const base62 = require('../utils/base62.js');
|
||||
|
||||
class Session {
|
||||
#id;
|
||||
@@ -88,20 +77,21 @@ class Session {
|
||||
*/
|
||||
cliCommand() {
|
||||
const sanitized = {
|
||||
target_id: escapeAndValidateBase62(this.#targetId),
|
||||
token: escapeAndValidateBase62(this.#token),
|
||||
target_id: base62.escapeAndValidate(this.#targetId),
|
||||
token: base62.escapeAndValidate(this.#token),
|
||||
addr: encodeURI(this.#addr),
|
||||
};
|
||||
|
||||
const command = [
|
||||
'connect',
|
||||
`-target-id=${sanitized.target_id}`,
|
||||
`-token=${sanitized.token}`,
|
||||
`-addr=${this.#addr}`,
|
||||
`-addr=${sanitized.addr}`,
|
||||
'-format=json',
|
||||
];
|
||||
|
||||
if (this.#hostId) {
|
||||
sanitized.host_id = escapeAndValidateBase62(this.#hostId);
|
||||
sanitized.host_id = base62.escapeAndValidate(this.#hostId);
|
||||
command.push(`-host-id=${sanitized.host_id}`);
|
||||
}
|
||||
return command;
|
||||
@@ -1,47 +1,7 @@
|
||||
const Session = require('./index.js');
|
||||
|
||||
class SessionManager {
|
||||
#sessions;
|
||||
|
||||
constructor() {
|
||||
this.#sessions = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for active sessions
|
||||
* @returns {boolean}
|
||||
*/
|
||||
get hasActiveSessions() {
|
||||
return Boolean(this.#sessions.find((session) => session.isActive));
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a session and track it.
|
||||
* Returns session proxy details if successfully started.
|
||||
* @param {string} addr
|
||||
* @param {string} target_id
|
||||
* @param {string} token
|
||||
* @param {string} host_id
|
||||
*/
|
||||
async start(addr, target_id, token, host_id) {
|
||||
const session = new Session(addr, target_id, token, host_id);
|
||||
this.#sessions.push(session);
|
||||
return session.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a session using identifier.
|
||||
* @param {string} session_id
|
||||
*/
|
||||
async stopById(session_id) {
|
||||
const session = this.#sessions.find((session) => session.id === session_id);
|
||||
return session && session.stop();
|
||||
}
|
||||
|
||||
stopAll() {
|
||||
this.#sessions.forEach((session) => session.stop());
|
||||
}
|
||||
}
|
||||
const SessionManager = require('../models/session-manager.js');
|
||||
|
||||
/**
|
||||
* Singleton for SessionManager
|
||||
*/
|
||||
const sessionManager = new SessionManager();
|
||||
module.exports = sessionManager;
|
||||
@@ -0,0 +1,14 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* Super paranoid shell quote/escape and validation. Input must be base62.
|
||||
* @param {string} str
|
||||
*/
|
||||
escapeAndValidate: (str) => {
|
||||
const candidate = str.toString();
|
||||
if (candidate.match(/^[A-Za-z0-9_]*$/)) return candidate;
|
||||
throw new Error(`
|
||||
Could not invoke command:
|
||||
input contained unsafe characters.
|
||||
`);
|
||||
},
|
||||
};
|
||||
@@ -245,7 +245,7 @@ module('Acceptance | projects | sessions', function (hooks) {
|
||||
|
||||
test('cancelling a session', async function (assert) {
|
||||
assert.expect(1);
|
||||
stubs.ipcService.withArgs('cancel');
|
||||
stubs.ipcService.withArgs('stop');
|
||||
later(async () => {
|
||||
run.cancelTimers();
|
||||
await click('tbody tr:first-child td:last-child button');
|
||||
@@ -267,7 +267,7 @@ module('Acceptance | projects | sessions', function (hooks) {
|
||||
|
||||
test('cancelling a session with ipc error shows notification', async function (assert) {
|
||||
assert.expect(1);
|
||||
stubs.ipcService.withArgs('cancel').throws();
|
||||
stubs.ipcService.withArgs('stop').throws();
|
||||
later(async () => {
|
||||
run.cancelTimers();
|
||||
await click('tbody tr:first-child td:last-child button');
|
||||
|
||||
@@ -271,7 +271,7 @@ module('Acceptance | projects | targets | sessions', function (hooks) {
|
||||
|
||||
test('cancelling a session with ipc error shows notification', async function (assert) {
|
||||
assert.expect(1);
|
||||
stubs.ipcService.withArgs('cancel').throws();
|
||||
stubs.ipcService.withArgs('stop').throws();
|
||||
later(async () => {
|
||||
run.cancelTimers();
|
||||
await click('tbody tr:first-child td:last-child button');
|
||||
|
||||
Reference in new issue
Block a user