feat: Add launch functionality in targets list view (#3035)
This commit is contained in:
1 parent
6554af1164
commit
27136eaa71
4 files changed
+153
-9
No files matched your search
@@ -68,3 +68,4 @@ show-errors: Show Errors
|
||||
hide-errors: Hide Errors
|
||||
edit-worker-filter: Edit Worker Filter
|
||||
add-worker-filter: Add Worker Filter
|
||||
open: Open
|
||||
@@ -26,6 +26,7 @@ export default class ScopesScopeProjectsTargetsIndexController extends Controlle
|
||||
@service store;
|
||||
@service can;
|
||||
@service intl;
|
||||
@service rdp;
|
||||
|
||||
// =attributes
|
||||
|
||||
@@ -244,6 +245,8 @@ export default class ScopesScopeProjectsTargetsIndexController extends Controlle
|
||||
'scopes.scope.projects.sessions.session',
|
||||
session_id,
|
||||
);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -311,4 +314,23 @@ export default class ScopesScopeProjectsTargetsIndexController extends Controlle
|
||||
async refresh() {
|
||||
await this.currentRoute.refreshAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick connect method used to call main connect method and
|
||||
* then launch RDP client
|
||||
* @param {TargetModel} target
|
||||
*/
|
||||
@action
|
||||
async quickConnectAndLaunchRdp(target) {
|
||||
try {
|
||||
const session = await this.connect(target);
|
||||
// Launch RDP client
|
||||
await this.rdp.launchRdpClient(session.id);
|
||||
} catch (error) {
|
||||
this.confirm
|
||||
.confirm(error.message, { isConnectError: true })
|
||||
// Retry
|
||||
.then(() => this.quickConnectAndLaunchRdp(target));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,14 +152,25 @@
|
||||
<div {{style display='inline-block'}}>
|
||||
{{#if (can 'connect target' B.data)}}
|
||||
{{#if (can 'read target' B.data)}}
|
||||
<Hds::Button
|
||||
data-test-targets-connect-button={{B.data.id}}
|
||||
@text={{t 'resources.session.actions.connect'}}
|
||||
@color='secondary'
|
||||
@route='scopes.scope.projects.targets.target'
|
||||
@model={{B.data.id}}
|
||||
@query={{hash isConnecting=true}}
|
||||
/>
|
||||
{{#if (and B.data.isRDP this.rdp.isPreferredRdpClientSet)}}
|
||||
<Hds::Button
|
||||
data-test-targets-open-button={{B.data.id}}
|
||||
@text={{t 'actions.open'}}
|
||||
@icon='external-link'
|
||||
@iconPosition='trailing'
|
||||
@color='secondary'
|
||||
{{on 'click' (fn this.quickConnectAndLaunchRdp B.data)}}
|
||||
/>
|
||||
{{else}}
|
||||
<Hds::Button
|
||||
data-test-targets-connect-button={{B.data.id}}
|
||||
@text={{t 'resources.session.actions.connect'}}
|
||||
@color='secondary'
|
||||
@route='scopes.scope.projects.targets.target'
|
||||
@model={{B.data.id}}
|
||||
@query={{hash isConnecting=true}}
|
||||
/>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<Hds::Button
|
||||
data-test-targets-connect-button={{B.data.id}}
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
STATUS_SESSION_ACTIVE,
|
||||
STATUS_SESSION_TERMINATED,
|
||||
} from 'api/models/session';
|
||||
import { TYPE_TARGET_RDP } from 'api/models/target';
|
||||
|
||||
module('Acceptance | projects | targets | index', function (hooks) {
|
||||
setupApplicationTest(hooks);
|
||||
@@ -43,7 +44,9 @@ module('Acceptance | projects | targets | index', function (hooks) {
|
||||
'[data-test-targets-sessions-flyout] .hds-flyout__title';
|
||||
const SESSIONS_FLYOUT_CLOSE_BUTTON =
|
||||
'[data-test-targets-sessions-flyout] .hds-flyout__dismiss';
|
||||
|
||||
const TARGET_OPEN_BUTTON = (id) => `[data-test-targets-open-button="${id}"]`;
|
||||
const TARGET_CONNECT_BUTTON = (id) =>
|
||||
`[data-test-targets-connect-button="${id}"]`;
|
||||
const instances = {
|
||||
scopes: {
|
||||
global: null,
|
||||
@@ -709,4 +712,111 @@ module('Acceptance | projects | targets | index', function (hooks) {
|
||||
.dom(activeSessionFlyoutButtonSelector(instances.session.targetId))
|
||||
.doesNotExist();
|
||||
});
|
||||
|
||||
test('shows `Open` button for RDP target with preferred client', async function (assert) {
|
||||
let rdpService = this.owner.lookup('service:rdp');
|
||||
rdpService.preferredRdpClient = 'windows-app';
|
||||
instances.target.update({
|
||||
type: TYPE_TARGET_RDP,
|
||||
});
|
||||
await visit(urls.targets);
|
||||
|
||||
assert.dom(TARGET_OPEN_BUTTON(instances.target.id)).exists();
|
||||
assert.dom(TARGET_OPEN_BUTTON(instances.target.id)).hasText('Open');
|
||||
assert.dom('[data-test-icon=external-link]').exists();
|
||||
});
|
||||
|
||||
test('shows `Connect` button for RDP target with no preferred client', async function (assert) {
|
||||
let rdpService = this.owner.lookup('service:rdp');
|
||||
rdpService.preferredRdpClient = 'none';
|
||||
instances.target.update({
|
||||
type: TYPE_TARGET_RDP,
|
||||
});
|
||||
await visit(urls.targets);
|
||||
|
||||
assert.dom(TARGET_CONNECT_BUTTON(instances.target.id)).exists();
|
||||
assert.dom(TARGET_CONNECT_BUTTON(instances.target.id)).hasText('Connect');
|
||||
assert.dom('[data-test-icon=external-link]').doesNotExist();
|
||||
});
|
||||
|
||||
test('shows `Connect` button for non-RDP target', async function (assert) {
|
||||
await visit(urls.targets);
|
||||
|
||||
assert.dom(TARGET_CONNECT_BUTTON(instances.target.id)).exists();
|
||||
assert.dom(TARGET_CONNECT_BUTTON(instances.target.id)).hasText('Connect');
|
||||
});
|
||||
|
||||
test('clicking `Open` button for RDP target calls launchRdpClient IPC', async function (assert) {
|
||||
this.ipcStub.withArgs('cliExists').returns(true);
|
||||
|
||||
const rdpService = this.owner.lookup('service:rdp');
|
||||
rdpService.preferredRdpClient = 'windows-app';
|
||||
instances.target.update({ type: TYPE_TARGET_RDP });
|
||||
|
||||
this.ipcStub.withArgs('connect').returns({
|
||||
session_id: instances.session.id,
|
||||
address: 'a_123',
|
||||
port: 'p_123',
|
||||
protocol: 'rdp',
|
||||
});
|
||||
this.ipcStub.withArgs('launchRdpClient').resolves();
|
||||
|
||||
// visit targets page
|
||||
await visit(urls.targets);
|
||||
|
||||
assert.dom(TARGET_OPEN_BUTTON(instances.target.id)).exists();
|
||||
|
||||
await click(TARGET_OPEN_BUTTON(instances.target.id));
|
||||
|
||||
assert.ok(this.ipcStub.calledWith('launchRdpClient', instances.session.id));
|
||||
});
|
||||
|
||||
test('clicking `Connect` button for RDP target without preferred client calls connect IPC', async function (assert) {
|
||||
this.ipcStub.withArgs('cliExists').returns(true);
|
||||
|
||||
const rdpService = this.owner.lookup('service:rdp');
|
||||
rdpService.preferredRdpClient = 'none';
|
||||
instances.target.update({ type: TYPE_TARGET_RDP });
|
||||
|
||||
this.ipcStub.withArgs('connect').returns({
|
||||
session_id: instances.session.id,
|
||||
address: 'a_123',
|
||||
port: 'p_123',
|
||||
protocol: 'rdp',
|
||||
});
|
||||
|
||||
// visit targets page
|
||||
await visit(urls.targets);
|
||||
|
||||
assert.dom(TARGET_CONNECT_BUTTON(instances.target.id)).exists();
|
||||
|
||||
await click(TARGET_CONNECT_BUTTON(instances.target.id));
|
||||
|
||||
assert.ok(this.ipcStub.calledWith('connect'));
|
||||
});
|
||||
|
||||
test('shows confirm modal when connection error occurs on launching rdp client', async function (assert) {
|
||||
let rdpService = this.owner.lookup('service:rdp');
|
||||
rdpService.preferredRdpClient = 'windows-app';
|
||||
instances.target.update({ type: TYPE_TARGET_RDP });
|
||||
|
||||
this.ipcStub.withArgs('cliExists').returns(true);
|
||||
// target quick connection is a success but launching RDP client fails
|
||||
this.ipcStub.withArgs('connect').returns({
|
||||
session_id: instances.session.id,
|
||||
address: 'a_123',
|
||||
port: 'p_123',
|
||||
protocol: 'rdp',
|
||||
});
|
||||
this.ipcStub.withArgs('launchRdpClient').rejects();
|
||||
|
||||
const confirmService = this.owner.lookup('service:confirm');
|
||||
confirmService.enabled = true;
|
||||
|
||||
await visit(urls.targets);
|
||||
await click(`[data-test-targets-open-button="${instances.target.id}"]`);
|
||||
|
||||
// Assert that the confirm modal appears
|
||||
assert.dom(HDS_DIALOG_MODAL).isVisible();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user